Nuvoton: Make SPI inter-frame (delay match configured suspend interval

In no MISO case, skip SPI read so that no more write/read delay contribute to SPI inter-frame delay when data is written successively.

Update targets:
-   NUMAKER_PFM_NANO130
-   NUMAKER_PFM_NUC472
-   NUMAKER_PFM_M453
-   NUMAKER_PFM_M487/NUMAKER_IOT_M487
-   NU_PFM_M2351_*
-   NUMAKER_IOT_M263A
-   NUMAKER_M252KG
pull/12454/head
Chun-Chieh Li 2020-02-17 15:00:09 +08:00
parent 3d038e55ee
commit 8df96ec50a
7 changed files with 169 additions and 39 deletions

View File

@ -285,17 +285,36 @@ void spi_frequency(spi_t *obj, int hz)
int spi_master_write(spi_t *obj, int value)
{
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
PinName spi_miso = obj->spi.pin_miso;
// NOTE: Data in receive FIFO can be read out via ICE.
SPI_ENABLE_SYNC(spi_base);
// Wait for tx buffer empty
/* Wait for TX FIFO not full */
while(! spi_writeable(obj));
SPI_WRITE_TX(spi_base, value);
// Wait for rx buffer full
while (! spi_readable(obj));
int value2 = SPI_READ_RX(spi_base);
/* Make inter-frame (SPI data frame) delay match configured suspend interval
* in no MISO case
*
* This API requires data write/read simultaneously. However, it can enlarge
* the inter-frame delay. The data flow for one call of this API would be:
* 1. Write data to TX FIFO when it is not full
* 2. Write delay consisting of TX FIFO to TX Shift Register...
* 3. Actual data transfer on SPI bus
* 4. Read delay consisting of RX FIFO from RX Shift Register...
* 5. Read data from RX FIFO when it is not empty
* Among above, S2&S4 contribute to the inter-frame delay.
*
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
* contribute to the inter-frame delay when data is written successively. The solution
* can cause RX FIFO overrun. Ignore it.
*/
int value2 = -1;
if (spi_miso != NC) {
/* Wait for RX FIFO not empty */
while (! spi_readable(obj));
value2 = SPI_READ_RX(spi_base);
}
/* We don't call SPI_DISABLE_SYNC here for performance. */

View File

@ -243,17 +243,36 @@ void spi_frequency(spi_t *obj, int hz)
int spi_master_write(spi_t *obj, int value)
{
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
PinName spi_miso = obj->spi.pin_miso;
// NOTE: Data in receive FIFO can be read out via ICE.
SPI_ENABLE_SYNC(spi_base);
// Wait for tx buffer empty
/* Wait for TX FIFO not full */
while(! spi_writeable(obj));
SPI_WRITE_TX(spi_base, value);
// Wait for rx buffer full
while (! spi_readable(obj));
int value2 = SPI_READ_RX(spi_base);
/* Make inter-frame (SPI data frame) delay match configured suspend interval
* in no MISO case
*
* This API requires data write/read simultaneously. However, it can enlarge
* the inter-frame delay. The data flow for one call of this API would be:
* 1. Write data to TX FIFO when it is not full
* 2. Write delay consisting of TX FIFO to TX Shift Register...
* 3. Actual data transfer on SPI bus
* 4. Read delay consisting of RX FIFO from RX Shift Register...
* 5. Read data from RX FIFO when it is not empty
* Among above, S2&S4 contribute to the inter-frame delay.
*
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
* contribute to the inter-frame delay when data is written successively. The solution
* can cause RX FIFO overrun. Ignore it.
*/
int value2 = -1;
if (spi_miso != NC) {
/* Wait for RX FIFO not empty */
while (! spi_readable(obj));
value2 = SPI_READ_RX(spi_base);
}
/* We don't call SPI_DISABLE_SYNC here for performance. */

View File

@ -264,17 +264,36 @@ void spi_frequency(spi_t *obj, int hz)
int spi_master_write(spi_t *obj, int value)
{
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
PinName spi_miso = obj->spi.pin_miso;
// NOTE: Data in receive FIFO can be read out via ICE.
SPI_ENABLE_SYNC(spi_base);
// Wait for tx buffer empty
/* Wait for TX FIFO not full */
while(! spi_writeable(obj));
SPI_WRITE_TX(spi_base, value);
// Wait for rx buffer full
while (! spi_readable(obj));
int value2 = SPI_READ_RX(spi_base);
/* Make inter-frame (SPI data frame) delay match configured suspend interval
* in no MISO case
*
* This API requires data write/read simultaneously. However, it can enlarge
* the inter-frame delay. The data flow for one call of this API would be:
* 1. Write data to TX FIFO when it is not full
* 2. Write delay consisting of TX FIFO to TX Shift Register...
* 3. Actual data transfer on SPI bus
* 4. Read delay consisting of RX FIFO from RX Shift Register...
* 5. Read data from RX FIFO when it is not empty
* Among above, S2&S4 contribute to the inter-frame delay.
*
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
* contribute to the inter-frame delay when data is written successively. The solution
* can cause RX FIFO overrun. Ignore it.
*/
int value2 = -1;
if (spi_miso != NC) {
/* Wait for RX FIFO not empty */
while (! spi_readable(obj));
value2 = SPI_READ_RX(spi_base);
}
/* We don't call SPI_DISABLE_SYNC here for performance. */

View File

@ -257,17 +257,36 @@ void spi_frequency(spi_t *obj, int hz)
int spi_master_write(spi_t *obj, int value)
{
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
PinName spi_miso = obj->spi.pin_miso;
// NOTE: Data in receive FIFO can be read out via ICE.
SPI_ENABLE_SYNC(spi_base);
// Wait for tx buffer empty
/* Wait for TX FIFO not full */
while(! spi_writeable(obj));
SPI_WRITE_TX(spi_base, value);
// Wait for rx buffer full
while (! spi_readable(obj));
int value2 = SPI_READ_RX(spi_base);
/* Make inter-frame (SPI data frame) delay match configured suspend interval
* in no MISO case
*
* This API requires data write/read simultaneously. However, it can enlarge
* the inter-frame delay. The data flow for one call of this API would be:
* 1. Write data to TX FIFO when it is not full
* 2. Write delay consisting of TX FIFO to TX Shift Register...
* 3. Actual data transfer on SPI bus
* 4. Read delay consisting of RX FIFO from RX Shift Register...
* 5. Read data from RX FIFO when it is not empty
* Among above, S2&S4 contribute to the inter-frame delay.
*
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
* contribute to the inter-frame delay when data is written successively. The solution
* can cause RX FIFO overrun. Ignore it.
*/
int value2 = -1;
if (spi_miso != NC) {
/* Wait for RX FIFO not empty */
while (! spi_readable(obj));
value2 = SPI_READ_RX(spi_base);
}
/* We don't call SPI_DISABLE_SYNC here for performance. */

View File

@ -270,17 +270,36 @@ void spi_frequency(spi_t *obj, int hz)
int spi_master_write(spi_t *obj, int value)
{
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
PinName spi_miso = obj->spi.pin_miso;
// NOTE: Data in receive FIFO can be read out via ICE.
SPI_ENABLE_SYNC(spi_base);
// Wait for tx buffer empty
/* Wait for TX FIFO not full */
while(! spi_writeable(obj));
SPI_WRITE_TX(spi_base, value);
// Wait for rx buffer full
while (! spi_readable(obj));
int value2 = SPI_READ_RX(spi_base);
/* Make inter-frame (SPI data frame) delay match configured suspend interval
* in no MISO case
*
* This API requires data write/read simultaneously. However, it can enlarge
* the inter-frame delay. The data flow for one call of this API would be:
* 1. Write data to TX FIFO when it is not full
* 2. Write delay consisting of TX FIFO to TX Shift Register...
* 3. Actual data transfer on SPI bus
* 4. Read delay consisting of RX FIFO from RX Shift Register...
* 5. Read data from RX FIFO when it is not empty
* Among above, S2&S4 contribute to the inter-frame delay.
*
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
* contribute to the inter-frame delay when data is written successively. The solution
* can cause RX FIFO overrun. Ignore it.
*/
int value2 = -1;
if (spi_miso != NC) {
/* Wait for RX FIFO not empty */
while (! spi_readable(obj));
value2 = SPI_READ_RX(spi_base);
}
/* We don't call SPI_DISABLE_SYNC here for performance. */

View File

@ -303,22 +303,38 @@ void spi_frequency(spi_t *obj, int hz)
int spi_master_write(spi_t *obj, int value)
{
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
PinName spi_miso = obj->spi.pin_miso;
// NOTE: Data in receive FIFO can be read out via ICE.
// NOTE:
// NUC472/M453/M487: SPI_CTL.SPIEN is controlled by software (in FIFO mode).
// NANO130: SPI_CTL.GO_BUSY is controlled by hardware in FIFO mode.
SPI_ENABLE_SYNC(spi_base);
// Wait for tx buffer empty
/* Wait for TX FIFO not full */
while(! spi_writeable(obj));
uint32_t TX = (NU_MODSUBINDEX(obj->spi.spi) == 0) ? ((uint32_t) &spi_base->TX0) : ((uint32_t) &spi_base->TX1);
M32(TX) = value;
// Wait for rx buffer full
while (! spi_readable(obj));
uint32_t RX = (NU_MODSUBINDEX(obj->spi.spi) == 0) ? ((uint32_t) &spi_base->RX0) : ((uint32_t) &spi_base->RX1);
int value2 = M32(RX);
/* Make inter-frame (SPI data frame) delay match configured suspend interval
* in no MISO case
*
* This API requires data write/read simultaneously. However, it can enlarge
* the inter-frame delay. The data flow for one call of this API would be:
* 1. Write data to TX FIFO when it is not full
* 2. Write delay consisting of TX FIFO to TX Shift Register...
* 3. Actual data transfer on SPI bus
* 4. Read delay consisting of RX FIFO from RX Shift Register...
* 5. Read data from RX FIFO when it is not empty
* Among above, S2&S4 contribute to the inter-frame delay.
*
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
* contribute to the inter-frame delay when data is written successively. The solution
* can cause RX FIFO overrun. Ignore it.
*/
int value2 = -1;
if (spi_miso != NC) {
/* Wait for RX FIFO not empty */
while (! spi_readable(obj));
uint32_t RX = (NU_MODSUBINDEX(obj->spi.spi) == 0) ? ((uint32_t) &spi_base->RX0) : ((uint32_t) &spi_base->RX1);
value2 = M32(RX);
}
/* We don't call SPI_DISABLE_SYNC here for performance. */

View File

@ -263,17 +263,36 @@ void spi_frequency(spi_t *obj, int hz)
int spi_master_write(spi_t *obj, int value)
{
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
PinName spi_miso = obj->spi.pin_miso;
// NOTE: Data in receive FIFO can be read out via ICE.
SPI_ENABLE_SYNC(spi_base);
// Wait for tx buffer empty
/* Wait for TX FIFO not full */
while(! spi_writeable(obj));
SPI_WRITE_TX(spi_base, value);
// Wait for rx buffer full
while (! spi_readable(obj));
int value2 = SPI_READ_RX(spi_base);
/* Make inter-frame (SPI data frame) delay match configured suspend interval
* in no MISO case
*
* This API requires data write/read simultaneously. However, it can enlarge
* the inter-frame delay. The data flow for one call of this API would be:
* 1. Write data to TX FIFO when it is not full
* 2. Write delay consisting of TX FIFO to TX Shift Register...
* 3. Actual data transfer on SPI bus
* 4. Read delay consisting of RX FIFO from RX Shift Register...
* 5. Read data from RX FIFO when it is not empty
* Among above, S2&S4 contribute to the inter-frame delay.
*
* To favor no MISO case, we skip S4&S5. Thus, S2 can overlap with S3 and doesn't
* contribute to the inter-frame delay when data is written successively. The solution
* can cause RX FIFO overrun. Ignore it.
*/
int value2 = -1;
if (spi_miso != NC) {
/* Wait for RX FIFO not empty */
while (! spi_readable(obj));
value2 = SPI_READ_RX(spi_base);
}
/* We don't call SPI_DISABLE_SYNC here for performance. */