32
32
#include "common-hal/microcontroller/Pin.h"
33
33
#include "supervisor/shared/rgb_led_status.h"
34
34
35
+ #include "esp_log.h"
36
+
37
+ static const char * TAG = "CircuitPython SPI" ;
38
+
35
39
static bool spi_never_reset [SOC_SPI_PERIPH_NUM ];
36
40
41
+ // Store one lock handle per device so that we can free it.
42
+ static spi_bus_lock_dev_handle_t lock_dev_handle [SOC_SPI_PERIPH_NUM ];
43
+ static intr_handle_t intr_handle [SOC_SPI_PERIPH_NUM ];
44
+
37
45
void spi_reset (void ) {
38
46
for (spi_host_device_t host_id = SPI2_HOST ; host_id < SOC_SPI_PERIPH_NUM ; host_id ++ ) {
39
47
if (spi_never_reset [host_id ]) {
40
48
continue ;
41
49
}
42
- spi_bus_free (host_id );
50
+ bool in_use = false;
51
+ if (lock_dev_handle [host_id ] != NULL ) {
52
+ spi_bus_lock_unregister_dev (lock_dev_handle [host_id ]);
53
+ lock_dev_handle [host_id ] = NULL ;
54
+ in_use = true;
55
+ }
56
+ if (intr_handle [host_id ] != NULL ) {
57
+ esp_intr_free (intr_handle [host_id ]);
58
+ intr_handle [host_id ] = NULL ;
59
+ in_use = true;
60
+ }
61
+ if (in_use ) {
62
+ spi_bus_free (host_id );
63
+ }
43
64
}
44
65
}
45
66
@@ -75,12 +96,24 @@ static bool bus_uses_iomux_pins(spi_host_device_t host, const spi_bus_config_t*
75
96
76
97
// End copied code.
77
98
78
- static bool _spi_bus_free (spi_host_device_t host_id ) {
99
+ static bool spi_bus_is_free (spi_host_device_t host_id ) {
79
100
return spi_bus_get_attr (host_id ) == NULL ;
80
101
}
81
102
82
103
static void spi_interrupt_handler (void * arg ) {
104
+ // busio_spi_obj_t *self = arg;
105
+ }
106
+
107
+ // The interrupt may get invoked by the bus lock.
108
+ static void spi_bus_intr_enable (void * self )
109
+ {
110
+ esp_intr_enable (((busio_spi_obj_t * )self )-> interrupt );
111
+ }
83
112
113
+ // The interrupt is always disabled by the ISR itself, not exposed
114
+ static void spi_bus_intr_disable (void * self )
115
+ {
116
+ esp_intr_disable (((busio_spi_obj_t * )self )-> interrupt );
84
117
}
85
118
86
119
void common_hal_busio_spi_construct (busio_spi_obj_t * self ,
@@ -103,12 +136,12 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
103
136
spi_host_device_t host_id = SPI1_HOST ;
104
137
self -> connected_through_gpio = true;
105
138
// Try and save SPI2 for pins that are on the IOMUX
106
- if (bus_uses_iomux_pins (SPI2_HOST , & bus_config ) && _spi_bus_free (SPI2_HOST )) {
139
+ if (bus_uses_iomux_pins (SPI2_HOST , & bus_config ) && spi_bus_is_free (SPI2_HOST )) {
107
140
host_id = SPI2_HOST ;
108
141
self -> connected_through_gpio = false;
109
- } else if (_spi_bus_free (SPI3_HOST )) {
142
+ } else if (spi_bus_is_free (SPI3_HOST )) {
110
143
host_id = SPI3_HOST ;
111
- } else if (_spi_bus_free (SPI2_HOST )) {
144
+ } else if (spi_bus_is_free (SPI2_HOST )) {
112
145
host_id = SPI2_HOST ;
113
146
}
114
147
if (host_id == SPI1_HOST ) {
@@ -121,21 +154,33 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
121
154
} else if (result == ESP_ERR_INVALID_ARG ) {
122
155
mp_raise_ValueError (translate ("Invalid pins" ));
123
156
}
157
+
158
+ // After this point, we need to deinit to free IDF memory so fill out self's pins.
159
+ self -> clock_pin = clock ;
160
+ self -> MOSI_pin = mosi ;
161
+ self -> MISO_pin = miso ;
162
+
124
163
spi_bus_lock_dev_config_t config = { .flags = 0 };
164
+ // The returned lock is stored in the bus lock but must be freed separately with
165
+ // spi_bus_lock_unregister_dev.
125
166
result = spi_bus_lock_register_dev (spi_bus_get_attr (host_id )-> lock ,
126
167
& config ,
127
168
& self -> lock );
128
169
if (result == ESP_ERR_NO_MEM ) {
170
+ common_hal_busio_spi_deinit (self );
129
171
mp_raise_msg (& mp_type_MemoryError , translate ("ESP-IDF memory allocation failed" ));
130
172
}
131
-
173
+ lock_dev_handle [ host_id ] = self -> lock ;
132
174
133
175
result = esp_intr_alloc (spicommon_irqsource_for_host (host_id ),
134
176
bus_config .intr_flags | ESP_INTR_FLAG_INTRDISABLED ,
135
177
spi_interrupt_handler , self , & self -> interrupt );
136
178
if (result == ESP_ERR_NO_MEM ) {
179
+ common_hal_busio_spi_deinit (self );
137
180
mp_raise_msg (& mp_type_MemoryError , translate ("ESP-IDF memory allocation failed" ));
138
181
}
182
+ intr_handle [host_id ] = self -> interrupt ;
183
+ spi_bus_lock_set_bg_control (spi_bus_get_attr (host_id )-> lock , spi_bus_intr_enable , spi_bus_intr_disable , self );
139
184
140
185
spi_hal_context_t * hal = & self -> hal_context ;
141
186
hal -> hw = NULL ; // Set by spi_hal_init
@@ -146,8 +191,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
146
191
// We don't use native CS.
147
192
hal -> cs_setup = 0 ;
148
193
hal -> cs_hold = 0 ;
149
- hal -> cs_pin_id = -1 ;
150
- hal -> timing_conf = & self -> timing_conf ;
194
+ hal -> cs_pin_id = 0 ;
151
195
152
196
hal -> sio = 1 ;
153
197
hal -> half_duplex = 0 ;
@@ -167,6 +211,13 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
167
211
hal -> io_mode = SPI_LL_IO_MODE_NORMAL ;
168
212
169
213
spi_hal_init (hal , host_id );
214
+ // This must be set after spi_hal_init.
215
+ hal -> timing_conf = & self -> timing_conf ;
216
+ if (hal -> hw == NULL ) {
217
+ ESP_LOGE (TAG , "SPI error %p" , hal -> hw );
218
+ }
219
+
220
+ common_hal_busio_spi_configure (self , 250000 , 0 , 0 , 8 );
170
221
}
171
222
172
223
void common_hal_busio_spi_never_reset (busio_spi_obj_t * self ) {
@@ -186,6 +237,14 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
186
237
return ;
187
238
}
188
239
spi_never_reset [self -> host_id ] = false;
240
+ if (self -> lock != NULL ) {
241
+ spi_bus_lock_unregister_dev (self -> lock );
242
+ lock_dev_handle [self -> host_id ] = NULL ;
243
+ }
244
+ if (self -> interrupt != NULL ) {
245
+ esp_intr_free (self -> interrupt );
246
+ intr_handle [self -> host_id ] = NULL ;
247
+ }
189
248
spi_bus_free (self -> host_id );
190
249
191
250
common_hal_reset_pin (self -> clock_pin );
@@ -218,7 +277,11 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
218
277
return false;
219
278
}
220
279
280
+ ESP_LOGI (TAG , "configure" );
281
+ ESP_LOGI (TAG , "real frequency %d" , self -> real_frequency );
282
+ ESP_LOGI (TAG , "timing_conf %p" , self -> hal_context .timing_conf );
221
283
spi_hal_setup_device (& self -> hal_context );
284
+ ESP_LOGI (TAG , "setup done" );
222
285
return true;
223
286
}
224
287
0 commit comments