1
1
/*
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
+ */
26
26
27
27
#include <stdio.h>
28
28
#include <stdint.h>
43
43
#define MICROPY_PY_MACHINE_SPI_LSB (1)
44
44
#endif
45
45
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
+ }
46
78
47
79
48
80
STATIC void machine_hw_spi_transfer (mp_obj_base_t * self_in , size_t len , const uint8_t * src , uint8_t * dest ) {
49
81
machine_hw_spi_obj_t * self = MP_OBJ_TO_PTR (self_in );
50
82
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" );
52
85
return ;
53
86
}
54
87
@@ -86,47 +119,92 @@ STATIC void machine_hw_spi_transfer(mp_obj_base_t *self_in, size_t len, const ui
86
119
87
120
STATIC void machine_hw_spi_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
88
121
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 );
93
126
}
94
127
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 );
97
144
esp_err_t ret ;
145
+ spi_host_device_t old_host = self -> host ;
98
146
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
+ }
114
151
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 ;
118
155
}
119
156
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
+
130
208
131
209
spi_bus_config_t buscfg = {
132
210
.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_
135
213
.quadwp_io_num = -1 ,
136
214
.quadhd_io_num = -1
137
215
};
216
+
138
217
spi_device_interface_config_t devcfg = {
139
218
.clock_speed_hz = self -> baudrate ,
140
219
.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_
146
225
147
226
//Initialize the SPI bus
148
227
// FIXME: Does the DMA matter? There are two
228
+
149
229
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
+
151
240
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" );
153
259
}
154
260
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 ) {
156
262
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 );
164
306
}
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 );
165
312
}
166
313
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
+
169
330
machine_hw_spi_obj_t * self = m_new_obj (machine_hw_spi_obj_t );
170
331
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
+
175
345
return MP_OBJ_FROM_PTR (self );
176
346
}
177
347
@@ -183,7 +353,7 @@ STATIC const mp_machine_spi_p_t machine_hw_spi_p = {
183
353
184
354
const mp_obj_type_t machine_hw_spi_type = {
185
355
{ & mp_type_type },
186
- .name = MP_QSTR_hw_spi ,
356
+ .name = MP_QSTR_SPI ,
187
357
.print = machine_hw_spi_print ,
188
358
.make_new = machine_hw_spi_make_new ,
189
359
.protocol = & machine_hw_spi_p ,
0 commit comments