Skip to content

Commit 043f68b

Browse files
authored
Merge pull request #12454 from OpenNuvoton/nuvoton_spi_no_miso
Nuvoton: Optimize spi_master_write(...) in case of no SPI MISO pin
2 parents 69a0542 + 8df96ec commit 043f68b

File tree

7 files changed

+169
-39
lines changed

7 files changed

+169
-39
lines changed

targets/TARGET_NUVOTON/TARGET_M2351/spi_api.c

+24-5
Original file line numberDiff line numberDiff line change
@@ -285,17 +285,36 @@ void spi_frequency(spi_t *obj, int hz)
285285
int spi_master_write(spi_t *obj, int value)
286286
{
287287
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
288+
PinName spi_miso = obj->spi.pin_miso;
288289

289-
// NOTE: Data in receive FIFO can be read out via ICE.
290290
SPI_ENABLE_SYNC(spi_base);
291291

292-
// Wait for tx buffer empty
292+
/* Wait for TX FIFO not full */
293293
while(! spi_writeable(obj));
294294
SPI_WRITE_TX(spi_base, value);
295295

296-
// Wait for rx buffer full
297-
while (! spi_readable(obj));
298-
int value2 = SPI_READ_RX(spi_base);
296+
/* Make inter-frame (SPI data frame) delay match configured suspend interval
297+
* in no MISO case
298+
*
299+
* This API requires data write/read simultaneously. However, it can enlarge
300+
* the inter-frame delay. The data flow for one call of this API would be:
301+
* 1. Write data to TX FIFO when it is not full
302+
* 2. Write delay consisting of TX FIFO to TX Shift Register...
303+
* 3. Actual data transfer on SPI bus
304+
* 4. Read delay consisting of RX FIFO from RX Shift Register...
305+
* 5. Read data from RX FIFO when it is not empty
306+
* Among above, S2&S4 contribute to the inter-frame delay.
307+
*
308+
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
309+
* contribute to the inter-frame delay when data is written successively. The solution
310+
* can cause RX FIFO overrun. Ignore it.
311+
*/
312+
int value2 = -1;
313+
if (spi_miso != NC) {
314+
/* Wait for RX FIFO not empty */
315+
while (! spi_readable(obj));
316+
value2 = SPI_READ_RX(spi_base);
317+
}
299318

300319
/* We don't call SPI_DISABLE_SYNC here for performance. */
301320

targets/TARGET_NUVOTON/TARGET_M251/spi_api.c

+24-5
Original file line numberDiff line numberDiff line change
@@ -243,17 +243,36 @@ void spi_frequency(spi_t *obj, int hz)
243243
int spi_master_write(spi_t *obj, int value)
244244
{
245245
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
246+
PinName spi_miso = obj->spi.pin_miso;
246247

247-
// NOTE: Data in receive FIFO can be read out via ICE.
248248
SPI_ENABLE_SYNC(spi_base);
249249

250-
// Wait for tx buffer empty
250+
/* Wait for TX FIFO not full */
251251
while(! spi_writeable(obj));
252252
SPI_WRITE_TX(spi_base, value);
253253

254-
// Wait for rx buffer full
255-
while (! spi_readable(obj));
256-
int value2 = SPI_READ_RX(spi_base);
254+
/* Make inter-frame (SPI data frame) delay match configured suspend interval
255+
* in no MISO case
256+
*
257+
* This API requires data write/read simultaneously. However, it can enlarge
258+
* the inter-frame delay. The data flow for one call of this API would be:
259+
* 1. Write data to TX FIFO when it is not full
260+
* 2. Write delay consisting of TX FIFO to TX Shift Register...
261+
* 3. Actual data transfer on SPI bus
262+
* 4. Read delay consisting of RX FIFO from RX Shift Register...
263+
* 5. Read data from RX FIFO when it is not empty
264+
* Among above, S2&S4 contribute to the inter-frame delay.
265+
*
266+
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
267+
* contribute to the inter-frame delay when data is written successively. The solution
268+
* can cause RX FIFO overrun. Ignore it.
269+
*/
270+
int value2 = -1;
271+
if (spi_miso != NC) {
272+
/* Wait for RX FIFO not empty */
273+
while (! spi_readable(obj));
274+
value2 = SPI_READ_RX(spi_base);
275+
}
257276

258277
/* We don't call SPI_DISABLE_SYNC here for performance. */
259278

targets/TARGET_NUVOTON/TARGET_M261/spi_api.c

+24-5
Original file line numberDiff line numberDiff line change
@@ -264,17 +264,36 @@ void spi_frequency(spi_t *obj, int hz)
264264
int spi_master_write(spi_t *obj, int value)
265265
{
266266
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
267+
PinName spi_miso = obj->spi.pin_miso;
267268

268-
// NOTE: Data in receive FIFO can be read out via ICE.
269269
SPI_ENABLE_SYNC(spi_base);
270270

271-
// Wait for tx buffer empty
271+
/* Wait for TX FIFO not full */
272272
while(! spi_writeable(obj));
273273
SPI_WRITE_TX(spi_base, value);
274274

275-
// Wait for rx buffer full
276-
while (! spi_readable(obj));
277-
int value2 = SPI_READ_RX(spi_base);
275+
/* Make inter-frame (SPI data frame) delay match configured suspend interval
276+
* in no MISO case
277+
*
278+
* This API requires data write/read simultaneously. However, it can enlarge
279+
* the inter-frame delay. The data flow for one call of this API would be:
280+
* 1. Write data to TX FIFO when it is not full
281+
* 2. Write delay consisting of TX FIFO to TX Shift Register...
282+
* 3. Actual data transfer on SPI bus
283+
* 4. Read delay consisting of RX FIFO from RX Shift Register...
284+
* 5. Read data from RX FIFO when it is not empty
285+
* Among above, S2&S4 contribute to the inter-frame delay.
286+
*
287+
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
288+
* contribute to the inter-frame delay when data is written successively. The solution
289+
* can cause RX FIFO overrun. Ignore it.
290+
*/
291+
int value2 = -1;
292+
if (spi_miso != NC) {
293+
/* Wait for RX FIFO not empty */
294+
while (! spi_readable(obj));
295+
value2 = SPI_READ_RX(spi_base);
296+
}
278297

279298
/* We don't call SPI_DISABLE_SYNC here for performance. */
280299

targets/TARGET_NUVOTON/TARGET_M451/spi_api.c

+24-5
Original file line numberDiff line numberDiff line change
@@ -257,17 +257,36 @@ void spi_frequency(spi_t *obj, int hz)
257257
int spi_master_write(spi_t *obj, int value)
258258
{
259259
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
260+
PinName spi_miso = obj->spi.pin_miso;
260261

261-
// NOTE: Data in receive FIFO can be read out via ICE.
262262
SPI_ENABLE_SYNC(spi_base);
263263

264-
// Wait for tx buffer empty
264+
/* Wait for TX FIFO not full */
265265
while(! spi_writeable(obj));
266266
SPI_WRITE_TX(spi_base, value);
267267

268-
// Wait for rx buffer full
269-
while (! spi_readable(obj));
270-
int value2 = SPI_READ_RX(spi_base);
268+
/* Make inter-frame (SPI data frame) delay match configured suspend interval
269+
* in no MISO case
270+
*
271+
* This API requires data write/read simultaneously. However, it can enlarge
272+
* the inter-frame delay. The data flow for one call of this API would be:
273+
* 1. Write data to TX FIFO when it is not full
274+
* 2. Write delay consisting of TX FIFO to TX Shift Register...
275+
* 3. Actual data transfer on SPI bus
276+
* 4. Read delay consisting of RX FIFO from RX Shift Register...
277+
* 5. Read data from RX FIFO when it is not empty
278+
* Among above, S2&S4 contribute to the inter-frame delay.
279+
*
280+
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
281+
* contribute to the inter-frame delay when data is written successively. The solution
282+
* can cause RX FIFO overrun. Ignore it.
283+
*/
284+
int value2 = -1;
285+
if (spi_miso != NC) {
286+
/* Wait for RX FIFO not empty */
287+
while (! spi_readable(obj));
288+
value2 = SPI_READ_RX(spi_base);
289+
}
271290

272291
/* We don't call SPI_DISABLE_SYNC here for performance. */
273292

targets/TARGET_NUVOTON/TARGET_M480/spi_api.c

+24-5
Original file line numberDiff line numberDiff line change
@@ -270,17 +270,36 @@ void spi_frequency(spi_t *obj, int hz)
270270
int spi_master_write(spi_t *obj, int value)
271271
{
272272
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
273+
PinName spi_miso = obj->spi.pin_miso;
273274

274-
// NOTE: Data in receive FIFO can be read out via ICE.
275275
SPI_ENABLE_SYNC(spi_base);
276276

277-
// Wait for tx buffer empty
277+
/* Wait for TX FIFO not full */
278278
while(! spi_writeable(obj));
279279
SPI_WRITE_TX(spi_base, value);
280280

281-
// Wait for rx buffer full
282-
while (! spi_readable(obj));
283-
int value2 = SPI_READ_RX(spi_base);
281+
/* Make inter-frame (SPI data frame) delay match configured suspend interval
282+
* in no MISO case
283+
*
284+
* This API requires data write/read simultaneously. However, it can enlarge
285+
* the inter-frame delay. The data flow for one call of this API would be:
286+
* 1. Write data to TX FIFO when it is not full
287+
* 2. Write delay consisting of TX FIFO to TX Shift Register...
288+
* 3. Actual data transfer on SPI bus
289+
* 4. Read delay consisting of RX FIFO from RX Shift Register...
290+
* 5. Read data from RX FIFO when it is not empty
291+
* Among above, S2&S4 contribute to the inter-frame delay.
292+
*
293+
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
294+
* contribute to the inter-frame delay when data is written successively. The solution
295+
* can cause RX FIFO overrun. Ignore it.
296+
*/
297+
int value2 = -1;
298+
if (spi_miso != NC) {
299+
/* Wait for RX FIFO not empty */
300+
while (! spi_readable(obj));
301+
value2 = SPI_READ_RX(spi_base);
302+
}
284303

285304
/* We don't call SPI_DISABLE_SYNC here for performance. */
286305

targets/TARGET_NUVOTON/TARGET_NANO100/spi_api.c

+25-9
Original file line numberDiff line numberDiff line change
@@ -303,22 +303,38 @@ void spi_frequency(spi_t *obj, int hz)
303303
int spi_master_write(spi_t *obj, int value)
304304
{
305305
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
306+
PinName spi_miso = obj->spi.pin_miso;
306307

307-
// NOTE: Data in receive FIFO can be read out via ICE.
308-
// NOTE:
309-
// NUC472/M453/M487: SPI_CTL.SPIEN is controlled by software (in FIFO mode).
310-
// NANO130: SPI_CTL.GO_BUSY is controlled by hardware in FIFO mode.
311308
SPI_ENABLE_SYNC(spi_base);
312309

313-
// Wait for tx buffer empty
310+
/* Wait for TX FIFO not full */
314311
while(! spi_writeable(obj));
315312
uint32_t TX = (NU_MODSUBINDEX(obj->spi.spi) == 0) ? ((uint32_t) &spi_base->TX0) : ((uint32_t) &spi_base->TX1);
316313
M32(TX) = value;
317314

318-
// Wait for rx buffer full
319-
while (! spi_readable(obj));
320-
uint32_t RX = (NU_MODSUBINDEX(obj->spi.spi) == 0) ? ((uint32_t) &spi_base->RX0) : ((uint32_t) &spi_base->RX1);
321-
int value2 = M32(RX);
315+
/* Make inter-frame (SPI data frame) delay match configured suspend interval
316+
* in no MISO case
317+
*
318+
* This API requires data write/read simultaneously. However, it can enlarge
319+
* the inter-frame delay. The data flow for one call of this API would be:
320+
* 1. Write data to TX FIFO when it is not full
321+
* 2. Write delay consisting of TX FIFO to TX Shift Register...
322+
* 3. Actual data transfer on SPI bus
323+
* 4. Read delay consisting of RX FIFO from RX Shift Register...
324+
* 5. Read data from RX FIFO when it is not empty
325+
* Among above, S2&S4 contribute to the inter-frame delay.
326+
*
327+
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
328+
* contribute to the inter-frame delay when data is written successively. The solution
329+
* can cause RX FIFO overrun. Ignore it.
330+
*/
331+
int value2 = -1;
332+
if (spi_miso != NC) {
333+
/* Wait for RX FIFO not empty */
334+
while (! spi_readable(obj));
335+
uint32_t RX = (NU_MODSUBINDEX(obj->spi.spi) == 0) ? ((uint32_t) &spi_base->RX0) : ((uint32_t) &spi_base->RX1);
336+
value2 = M32(RX);
337+
}
322338

323339
/* We don't call SPI_DISABLE_SYNC here for performance. */
324340

targets/TARGET_NUVOTON/TARGET_NUC472/spi_api.c

+24-5
Original file line numberDiff line numberDiff line change
@@ -263,17 +263,36 @@ void spi_frequency(spi_t *obj, int hz)
263263
int spi_master_write(spi_t *obj, int value)
264264
{
265265
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
266+
PinName spi_miso = obj->spi.pin_miso;
266267

267-
// NOTE: Data in receive FIFO can be read out via ICE.
268268
SPI_ENABLE_SYNC(spi_base);
269269

270-
// Wait for tx buffer empty
270+
/* Wait for TX FIFO not full */
271271
while(! spi_writeable(obj));
272272
SPI_WRITE_TX(spi_base, value);
273273

274-
// Wait for rx buffer full
275-
while (! spi_readable(obj));
276-
int value2 = SPI_READ_RX(spi_base);
274+
/* Make inter-frame (SPI data frame) delay match configured suspend interval
275+
* in no MISO case
276+
*
277+
* This API requires data write/read simultaneously. However, it can enlarge
278+
* the inter-frame delay. The data flow for one call of this API would be:
279+
* 1. Write data to TX FIFO when it is not full
280+
* 2. Write delay consisting of TX FIFO to TX Shift Register...
281+
* 3. Actual data transfer on SPI bus
282+
* 4. Read delay consisting of RX FIFO from RX Shift Register...
283+
* 5. Read data from RX FIFO when it is not empty
284+
* Among above, S2&S4 contribute to the inter-frame delay.
285+
*
286+
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
287+
* contribute to the inter-frame delay when data is written successively. The solution
288+
* can cause RX FIFO overrun. Ignore it.
289+
*/
290+
int value2 = -1;
291+
if (spi_miso != NC) {
292+
/* Wait for RX FIFO not empty */
293+
while (! spi_readable(obj));
294+
value2 = SPI_READ_RX(spi_base);
295+
}
277296

278297
/* We don't call SPI_DISABLE_SYNC here for performance. */
279298

0 commit comments

Comments
 (0)