Skip to content
This repository was archived by the owner on Sep 6, 2023. It is now read-only.

Commit c6af5a7

Browse files
committed
esp32/machine_hw_spi.*: Updated to make spi_obj.init(...) idiom work
1 parent d0c792c commit c6af5a7

File tree

2 files changed

+274
-101
lines changed

2 files changed

+274
-101
lines changed

esp32/machine_hw_spi.c

Lines changed: 246 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
/*
2-
* This file is part of the MicroPython project, http://micropython.org/
3-
*
4-
* The MIT License (MIT)
5-
*
6-
* Copyright (c) 2016 Damien P. George
7-
*
8-
* Permission is hereby granted, free of charge, to any person obtaining a copy
9-
* of this software and associated documentation files (the "Software"), to deal
10-
* in the Software without restriction, including without limitation the rights
11-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12-
* copies of the Software, and to permit persons to whom the Software is
13-
* furnished to do so, subject to the following conditions:
14-
*
15-
* The above copyright notice and this permission notice shall be included in
16-
* all copies or substantial portions of the Software.
17-
*
18-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24-
* THE SOFTWARE.
25-
*/
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Damien P. George
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
2626

2727
#include <stdio.h>
2828
#include <stdint.h>
@@ -43,12 +43,45 @@
4343
#define MICROPY_PY_MACHINE_SPI_LSB (1)
4444
#endif
4545

46+
#define MACHINE_HW_SPI_DEBUG_PRINTF(args...) printf(args)
47+
48+
STATIC void machine_hw_spi_deinit_internal(spi_host_device_t host, spi_device_handle_t* spi) {
49+
50+
switch(spi_bus_remove_device(*spi)) {
51+
case ESP_ERR_INVALID_ARG:
52+
mp_raise_msg(&mp_type_OSError, "Invalid configuration");
53+
return;
54+
55+
case ESP_ERR_INVALID_STATE:
56+
mp_raise_msg(&mp_type_OSError, "SPI device already freed");
57+
return;
58+
}
59+
60+
switch(spi_bus_free(host)) {
61+
case ESP_ERR_INVALID_ARG:
62+
mp_raise_msg(&mp_type_OSError, "Invalid configuration");
63+
return;
64+
65+
case ESP_ERR_INVALID_STATE:
66+
mp_raise_msg(&mp_type_OSError, "SPI bus already freed");
67+
return;
68+
}
69+
}
70+
71+
STATIC void machine_hw_spi_deinit(mp_obj_base_t *self_in) {
72+
machine_hw_spi_obj_t *self = (machine_hw_spi_obj_t*)self_in;
73+
if (self->state == MACHINE_HW_SPI_STATE_INIT) {
74+
self->state = MACHINE_HW_SPI_STATE_DEINIT;
75+
machine_hw_spi_deinit_internal(self->host, &self->spi);
76+
}
77+
}
4678

4779

4880
STATIC void machine_hw_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
4981
machine_hw_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
5082
int bits_to_send = len * self->bits;
51-
if (self->deinitialized) {
83+
if (self->state == MACHINE_HW_SPI_STATE_DEINIT) {
84+
mp_raise_msg(&mp_type_OSError, "Transfer on deinitialized SPI");
5285
return;
5386
}
5487

@@ -86,47 +119,92 @@ STATIC void machine_hw_spi_transfer(mp_obj_base_t *self_in, size_t len, const ui
86119

87120
STATIC void machine_hw_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
88121
machine_hw_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
89-
mp_printf(print, "hw_spi(id=%u, baudrate=%u, polarity=%u, phase=%u, bits=%u, firstbit=%u, sck=%d, mosi=%d, miso=%d)",
90-
self->host, self->baudrate, self->polarity,
91-
self->phase, self->bits, self->firstbit,
92-
self->sck, self->mosi, self->miso );
122+
mp_printf(print, "SPI(id=%u, baudrate=%u, polarity=%u, phase=%u, bits=%u, firstbit=%u, sck=%d, mosi=%d, miso=%d)",
123+
self->host, self->baudrate, self->polarity,
124+
self->phase, self->bits, self->firstbit,
125+
self->sck, self->mosi, self->miso );
93126
}
94127

95-
STATIC void machine_hw_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
96-
machine_hw_spi_obj_t *self = (machine_hw_spi_obj_t*)self_in;
128+
STATIC void machine_hw_spi_init_internal(
129+
machine_hw_spi_obj_t *self,
130+
int8_t host,
131+
int32_t baudrate,
132+
int8_t polarity,
133+
int8_t phase,
134+
int8_t bits,
135+
int8_t firstbit,
136+
int8_t sck,
137+
int8_t mosi,
138+
int8_t miso) {
139+
bool changed = false;
140+
MACHINE_HW_SPI_DEBUG_PRINTF("machine_hw_spi_init_internal(self, host = %d, baudrate = %d, polarity = %d, phase = %d, bits = %d, firstbit = %d, sck = %d, mosi = %d, miso = %d)\n", host, baudrate, polarity, phase, bits, firstbit, sck, mosi, miso);
141+
142+
143+
MACHINE_HW_SPI_DEBUG_PRINTF("machine_hw_spi_init_internal old values: host = %d, baudrate = %d, polarity = %d, phase = %d, bits = %d, firstbit = %d, sck = %d, mosi = %d, miso = %d)\n", self->host, self->baudrate, self->polarity, self->phase, self->bits, self->firstbit, self->sck, self->mosi, self->miso);
97144
esp_err_t ret;
145+
spi_host_device_t old_host = self->host;
98146

99-
enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso };
100-
static const mp_arg_t allowed_args[] = {
101-
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = 1} },
102-
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 500000} },
103-
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
104-
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
105-
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
106-
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_PY_MACHINE_SPI_MSB} },
107-
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
108-
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
109-
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
110-
};
111-
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
112-
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args),
113-
allowed_args, args);
147+
if (host != -1 && host != self->host) {
148+
self->host = host;
149+
changed = true;
150+
}
114151

115-
int host = args[ARG_id].u_int;
116-
if (host != HSPI_HOST && host != VSPI_HOST) {
117-
mp_raise_ValueError("SPI ID must be either hw_spi(1) or VSPI(2)");
152+
if (baudrate != -1 && baudrate != self->baudrate) {
153+
self->baudrate = baudrate;
154+
changed = true;
118155
}
119156

120-
self->host = host;
121-
self->baudrate = args[ARG_baudrate].u_int;
122-
self->polarity = args[ARG_polarity].u_int ? 1 : 0;
123-
self->phase = args[ARG_phase].u_int ? 1 : 0;
124-
self->bits = args[ARG_bits].u_int;
125-
self->firstbit = args[ARG_firstbit].u_int;
126-
self->sck = args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sck].u_obj);
127-
self->miso = args[ARG_miso].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_miso].u_obj);
128-
self->mosi = args[ARG_mosi].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_mosi].u_obj);
129-
self->deinitialized = false;
157+
if (polarity != -1 && polarity != self->polarity) {
158+
self->polarity = polarity;
159+
changed = true;
160+
}
161+
162+
if (phase != -1 && phase != self->phase) {
163+
self->phase = phase;
164+
changed = true;
165+
}
166+
167+
if (bits != -1 && bits != self->bits) {
168+
self->bits = bits;
169+
changed = true;
170+
}
171+
172+
if (firstbit != -1 && firstbit != self->firstbit) {
173+
self->firstbit = firstbit;
174+
changed = true;
175+
}
176+
177+
if (sck != -2 && sck != self->sck) {
178+
self->sck = sck;
179+
changed = true;
180+
}
181+
182+
if (mosi != -2 && mosi != self->mosi) {
183+
self->mosi = mosi;
184+
changed = true;
185+
}
186+
187+
if (miso != -2 && miso != self->miso) {
188+
self->miso = miso;
189+
changed = true;
190+
}
191+
192+
if (self->host != HSPI_HOST && self->host != VSPI_HOST) {
193+
mp_raise_ValueError("SPI ID must be either HSPI(1) or VSPI(2)");
194+
}
195+
196+
if (changed) {
197+
if (self->state == MACHINE_HW_SPI_STATE_INIT) {
198+
MACHINE_HW_SPI_DEBUG_PRINTF("machine_hw_spi_init_internal calling deinit()\n");
199+
self->state = MACHINE_HW_SPI_STATE_DEINIT;
200+
machine_hw_spi_deinit_internal(old_host, &self->spi);
201+
}
202+
} else {
203+
return; // no changes
204+
}
205+
206+
MACHINE_HW_SPI_DEBUG_PRINTF("machine_hw_spi_init_internal new values: host = %d, baudrate = %d, polarity = %d, phase = %d, bits = %d, firstbit = %d, sck = %d, mosi = %d, miso = %d)\n", self->host, self->baudrate, self->polarity, self->phase, self->bits, self->firstbit, self->sck, self->mosi, self->miso);
207+
130208

131209
spi_bus_config_t buscfg = {
132210
.miso_io_num = self->miso,
@@ -135,6 +213,7 @@ STATIC void machine_hw_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_
135213
.quadwp_io_num = -1,
136214
.quadhd_io_num = -1
137215
};
216+
138217
spi_device_interface_config_t devcfg = {
139218
.clock_speed_hz = self->baudrate,
140219
.mode = self->phase | (self->polarity << 1),
@@ -146,32 +225,123 @@ STATIC void machine_hw_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_
146225

147226
//Initialize the SPI bus
148227
// FIXME: Does the DMA matter? There are two
228+
149229
ret = spi_bus_initialize(self->host, &buscfg, 1);
150-
assert(ret == ESP_OK);
230+
switch (ret) {
231+
case ESP_ERR_INVALID_ARG:
232+
mp_raise_msg(&mp_type_OSError, "Invalid configuration");
233+
return;
234+
235+
case ESP_ERR_INVALID_STATE:
236+
mp_raise_msg(&mp_type_OSError, "SPI device already in use");
237+
return;
238+
}
239+
151240
ret = spi_bus_add_device(self->host, &devcfg, &self->spi);
152-
assert(ret == ESP_OK);
241+
switch (ret) {
242+
case ESP_ERR_INVALID_ARG:
243+
mp_raise_msg(&mp_type_OSError, "Invalid configuration");
244+
spi_bus_free(self->host);
245+
return;
246+
247+
case ESP_ERR_NO_MEM:
248+
mp_raise_msg(&mp_type_OSError, "Out of memory");
249+
spi_bus_free(self->host);
250+
return;
251+
252+
case ESP_ERR_NOT_FOUND:
253+
mp_raise_msg(&mp_type_OSError, "No free CS slots");
254+
spi_bus_free(self->host);
255+
return;
256+
}
257+
self->state = MACHINE_HW_SPI_STATE_INIT;
258+
MACHINE_HW_SPI_DEBUG_PRINTF("machine_hw_spi_init_internal() returning\n");
153259
}
154260

155-
STATIC void machine_hw_spi_deinit(mp_obj_base_t *self_in) {
261+
STATIC void machine_hw_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
156262
machine_hw_spi_obj_t *self = (machine_hw_spi_obj_t*)self_in;
157-
esp_err_t ret;
158-
if (!self->deinitialized) {
159-
self->deinitialized = true;
160-
ret = spi_bus_remove_device(self->spi);
161-
assert(ret == ESP_OK);
162-
ret = spi_bus_free(self->host);
163-
assert(ret == ESP_OK);
263+
264+
enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso };
265+
static const mp_arg_t allowed_args[] = {
266+
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = -1} },
267+
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
268+
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
269+
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
270+
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
271+
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
272+
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
273+
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
274+
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
275+
};
276+
277+
278+
279+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
280+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args),
281+
allowed_args, args);
282+
int8_t sck, mosi, miso;
283+
284+
if(args[ARG_sck].u_obj == MP_OBJ_NULL) {
285+
sck = -2;
286+
} else if (args[ARG_sck].u_obj == mp_const_none) {
287+
sck = -1;
288+
} else {
289+
sck = machine_pin_get_id(args[ARG_sck].u_obj);
290+
}
291+
292+
if(args[ARG_miso].u_obj == MP_OBJ_NULL) {
293+
miso = -2;
294+
} else if (args[ARG_miso].u_obj == mp_const_none) {
295+
miso = -1;
296+
} else {
297+
miso = machine_pin_get_id(args[ARG_miso].u_obj);
298+
}
299+
300+
if(args[ARG_mosi].u_obj == MP_OBJ_NULL) {
301+
mosi = -2;
302+
} else if (args[ARG_mosi].u_obj == mp_const_none) {
303+
mosi = -1;
304+
} else {
305+
mosi = machine_pin_get_id(args[ARG_mosi].u_obj);
164306
}
307+
308+
MACHINE_HW_SPI_DEBUG_PRINTF ("before calling internal\n");
309+
machine_hw_spi_init_internal( self, args[ARG_id].u_int, args[ARG_baudrate].u_int,
310+
args[ARG_polarity].u_int, args[ARG_phase].u_int, args[ARG_bits].u_int,
311+
args[ARG_firstbit].u_int, sck, miso, mosi);
165312
}
166313

167-
mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
168-
// args[0] holds the id of the peripheral
314+
mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
315+
enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso };
316+
static const mp_arg_t allowed_args[] = {
317+
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = -1} },
318+
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 500000} },
319+
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
320+
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
321+
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
322+
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_PY_MACHINE_SPI_MSB} },
323+
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
324+
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
325+
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
326+
};
327+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
328+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
329+
169330
machine_hw_spi_obj_t *self = m_new_obj(machine_hw_spi_obj_t);
170331
self->base.type = &machine_hw_spi_type;
171-
// set defaults
172-
mp_map_t kw_args;
173-
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
174-
machine_hw_spi_init((mp_obj_base_t*)self, n_args, args, &kw_args);
332+
333+
machine_hw_spi_init_internal(
334+
self,
335+
args[ARG_id].u_int,
336+
args[ARG_baudrate].u_int,
337+
args[ARG_polarity].u_int,
338+
args[ARG_phase].u_int,
339+
args[ARG_bits].u_int,
340+
args[ARG_firstbit].u_int,
341+
args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sck].u_obj),
342+
args[ARG_miso].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_miso].u_obj),
343+
args[ARG_mosi].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_mosi].u_obj));
344+
175345
return MP_OBJ_FROM_PTR(self);
176346
}
177347

@@ -183,7 +353,7 @@ STATIC const mp_machine_spi_p_t machine_hw_spi_p = {
183353

184354
const mp_obj_type_t machine_hw_spi_type = {
185355
{ &mp_type_type },
186-
.name = MP_QSTR_hw_spi,
356+
.name = MP_QSTR_SPI,
187357
.print = machine_hw_spi_print,
188358
.make_new = machine_hw_spi_make_new,
189359
.protocol = &machine_hw_spi_p,

0 commit comments

Comments
 (0)