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>
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
4880STATIC 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
87120STATIC 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
184354const 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