@@ -71,6 +71,34 @@ static struct nu_spi_var spi4_var = {
71
71
#endif
72
72
};
73
73
74
+ /* Synchronous version of SPI_ENABLE()/SPI_DISABLE() macros
75
+ *
76
+ * The SPI peripheral clock is asynchronous with the system clock. In order to make sure the SPI
77
+ * control logic is enabled/disabled, this bit indicates the real status of SPI controller.
78
+ *
79
+ * NOTE: All configurations shall be ready before calling SPI_ENABLE_SYNC().
80
+ * NOTE: Before changing the configurations of SPIx_CTL, SPIx_CLKDIV, SPIx_SSCTL and SPIx_FIFOCTL registers,
81
+ * user shall clear the SPIEN (SPIx_CTL[0]) and confirm the SPIENSTS (SPIx_STATUS[15]) is 0
82
+ * (by SPI_DISABLE_SYNC here).
83
+ */
84
+ __STATIC_INLINE void SPI_ENABLE_SYNC (SPI_T * spi_base )
85
+ {
86
+ if (! (spi_base -> CTL & SPI_CTL_SPIEN_Msk )) {
87
+ SPI_ENABLE (spi_base );
88
+ }
89
+ while (! (spi_base -> STATUS & SPI_STATUS_SPIENSTS_Msk ));
90
+ }
91
+ __STATIC_INLINE void SPI_DISABLE_SYNC (SPI_T * spi_base )
92
+ {
93
+ if (spi_base -> CTL & SPI_CTL_SPIEN_Msk ) {
94
+ // NOTE: SPI H/W may get out of state without the busy check.
95
+ while (SPI_IS_BUSY (spi_base ));
96
+
97
+ SPI_DISABLE (spi_base );
98
+ }
99
+ while (spi_base -> STATUS & SPI_STATUS_SPIENSTS_Msk );
100
+ }
101
+
74
102
#if DEVICE_SPI_ASYNCH
75
103
static void spi_enable_vector_interrupt (spi_t * obj , uint32_t handler , uint8_t enable );
76
104
static void spi_master_enable_interrupt (spi_t * obj , uint8_t enable );
@@ -184,10 +212,7 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
184
212
185
213
SPI_T * spi_base = (SPI_T * ) NU_MODBASE (obj -> spi .spi );
186
214
187
- // NOTE 1: All configurations should be ready before enabling SPI peripheral.
188
- // NOTE 2: Re-configuration is allowed only as SPI peripheral is idle.
189
- while (SPI_IS_BUSY (spi_base ));
190
- SPI_DISABLE (spi_base );
215
+ SPI_DISABLE_SYNC (spi_base );
191
216
192
217
SPI_Open (spi_base ,
193
218
slave ? SPI_SLAVE : SPI_MASTER ,
@@ -212,15 +237,14 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
212
237
}
213
238
214
239
// NOTE: M451's/M480's SPI_Open() will enable SPI transfer (SPI_CTL_SPIEN_Msk). This will violate judgement of spi_active(). Disable it.
215
- SPI_DISABLE (spi_base );
240
+ SPI_DISABLE_SYNC (spi_base );
216
241
}
217
242
218
243
void spi_frequency (spi_t * obj , int hz )
219
244
{
220
245
SPI_T * spi_base = (SPI_T * ) NU_MODBASE (obj -> spi .spi );
221
246
222
- while (SPI_IS_BUSY (spi_base ));
223
- SPI_DISABLE (spi_base );
247
+ SPI_DISABLE_SYNC (spi_base );
224
248
225
249
SPI_SetBusClock ((SPI_T * ) NU_MODBASE (obj -> spi .spi ), hz );
226
250
}
@@ -231,7 +255,7 @@ int spi_master_write(spi_t *obj, int value)
231
255
SPI_T * spi_base = (SPI_T * ) NU_MODBASE (obj -> spi .spi );
232
256
233
257
// NOTE: Data in receive FIFO can be read out via ICE.
234
- SPI_ENABLE (spi_base );
258
+ SPI_ENABLE_SYNC (spi_base );
235
259
236
260
// Wait for tx buffer empty
237
261
while (! spi_writeable (obj ));
@@ -241,7 +265,7 @@ int spi_master_write(spi_t *obj, int value)
241
265
while (! spi_readable (obj ));
242
266
int value2 = SPI_READ_RX (spi_base );
243
267
244
- SPI_DISABLE (spi_base );
268
+ SPI_DISABLE_SYNC (spi_base );
245
269
246
270
return value2 ;
247
271
}
@@ -266,7 +290,7 @@ int spi_slave_receive(spi_t *obj)
266
290
{
267
291
SPI_T * spi_base = (SPI_T * ) NU_MODBASE (obj -> spi .spi );
268
292
269
- SPI_ENABLE (spi_base );
293
+ SPI_ENABLE_SYNC (spi_base );
270
294
271
295
return spi_readable (obj );
272
296
};
@@ -275,7 +299,7 @@ int spi_slave_read(spi_t *obj)
275
299
{
276
300
SPI_T * spi_base = (SPI_T * ) NU_MODBASE (obj -> spi .spi );
277
301
278
- SPI_ENABLE (spi_base );
302
+ SPI_ENABLE_SYNC (spi_base );
279
303
280
304
// Wait for rx buffer full
281
305
while (! spi_readable (obj ));
@@ -287,7 +311,7 @@ void spi_slave_write(spi_t *obj, int value)
287
311
{
288
312
SPI_T * spi_base = (SPI_T * ) NU_MODBASE (obj -> spi .spi );
289
313
290
- SPI_ENABLE (spi_base );
314
+ SPI_ENABLE_SYNC (spi_base );
291
315
292
316
// Wait for tx buffer empty
293
317
while (! spi_writeable (obj ));
@@ -320,7 +344,7 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx,
320
344
spi_enable_event (obj , event , 1 );
321
345
spi_buffer_set (obj , tx , tx_length , rx , rx_length );
322
346
323
- SPI_ENABLE (spi_base );
347
+ SPI_ENABLE_SYNC (spi_base );
324
348
325
349
if (obj -> spi .dma_usage == DMA_USAGE_NEVER ) {
326
350
// Interrupt way
@@ -428,9 +452,8 @@ void spi_abort_asynch(spi_t *obj)
428
452
spi_enable_vector_interrupt (obj , 0 , 0 );
429
453
spi_master_enable_interrupt (obj , 0 );
430
454
431
- // NOTE: SPI H/W may get out of state without the busy check.
432
- while (SPI_IS_BUSY (spi_base ));
433
- SPI_DISABLE (spi_base );
455
+ /* Necessary for accessing FIFOCTL below */
456
+ SPI_DISABLE_SYNC (spi_base );
434
457
435
458
SPI_ClearRxFIFO (spi_base );
436
459
SPI_ClearTxFIFO (spi_base );
0 commit comments