[Nuvoton] Fix redundant SPI clock generation

Fix SPI clocks are generated redundantly at the end of transfer.

This is also to fix FPGA CI test mbed_hal_fpga_ci_test_shield-spi/
SPI - async mode.
pull/11152/head
Chun-Chieh Li 2019-07-18 18:40:14 +08:00
parent 80c21aeff5
commit d46c6fea47
10 changed files with 37 additions and 59 deletions

View File

@ -84,6 +84,7 @@ struct spi_s {
int dma_chn_id_tx;
int dma_chn_id_rx;
uint32_t event;
uint32_t txrx_rmn; // Track tx/rx frames remaining in interrupt way
uint32_t hdlr_async;
};

View File

@ -407,6 +407,9 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx,
SPI_ENABLE_SYNC(spi_base);
// Initialize total SPI transfer frames
obj->spi.txrx_rmn = NU_MAX(tx_length, rx_length);
if (obj->spi.dma_usage == DMA_USAGE_NEVER) {
// Interrupt way
spi_master_write_asynch(obj, spi_fifo_depth(obj) / 2);
@ -677,16 +680,12 @@ static uint32_t spi_event_check(spi_t *obj)
static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
{
uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_tx = NU_MAX(tx_rmn, rx_rmn);
max_tx = NU_MIN(max_tx, tx_limit);
uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8;
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer) + bytes_per_word * obj->tx_buff.pos;
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
while ((n_words < max_tx) && spi_writeable(obj)) {
while (obj->spi.txrx_rmn && spi_writeable(obj)) {
if (spi_is_tx_complete(obj)) {
// Transmit dummy as transmit buffer is empty
SPI_WRITE_TX(spi_base, 0);
@ -709,6 +708,7 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
obj->tx_buff.pos ++;
}
n_words ++;
obj->spi.txrx_rmn --;
}
//Return the number of words that have been sent
@ -729,15 +729,12 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
static uint32_t spi_master_read_asynch(spi_t *obj)
{
uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_rx = NU_MAX(tx_rmn, rx_rmn);
uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8;
uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer) + bytes_per_word * obj->rx_buff.pos;
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
while ((n_words < max_rx) && spi_readable(obj)) {
while (spi_readable(obj)) {
if (spi_is_rx_complete(obj)) {
// Disregard as receive buffer is full
SPI_READ_RX(spi_base);

View File

@ -83,15 +83,12 @@ struct spi_s {
PinName pin_sclk;
PinName pin_ssel;
//void (*vec)(void);
// Async transfer related fields
DMAUsage dma_usage;
int dma_chn_id_tx;
int dma_chn_id_rx;
uint32_t event;
//void (*irq_handler_tx_async)(void);
//void (*irq_handler_rx_async)(void);
uint32_t txrx_rmn; // Track tx/rx frames remaining in interrupt way
};
struct i2c_s {

View File

@ -381,6 +381,9 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx,
SPI_ENABLE_SYNC(spi_base);
// Initialize total SPI transfer frames
obj->spi.txrx_rmn = NU_MAX(tx_length, rx_length);
if (obj->spi.dma_usage == DMA_USAGE_NEVER) {
// Interrupt way
spi_master_write_asynch(obj, NU_SPI_FIFO_DEPTH / 2);
@ -649,16 +652,12 @@ static uint32_t spi_event_check(spi_t *obj)
static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
{
uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_tx = NU_MAX(tx_rmn, rx_rmn);
max_tx = NU_MIN(max_tx, tx_limit);
uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8;
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer) + bytes_per_word * obj->tx_buff.pos;
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
while ((n_words < max_tx) && spi_writeable(obj)) {
while (obj->spi.txrx_rmn && spi_writeable(obj)) {
if (spi_is_tx_complete(obj)) {
// Transmit dummy as transmit buffer is empty
SPI_WRITE_TX(spi_base, 0);
@ -682,6 +681,7 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
obj->tx_buff.pos ++;
}
n_words ++;
obj->spi.txrx_rmn --;
}
//Return the number of words that have been sent
@ -702,15 +702,12 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
static uint32_t spi_master_read_asynch(spi_t *obj)
{
uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_rx = NU_MAX(tx_rmn, rx_rmn);
uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8;
uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer) + bytes_per_word * obj->rx_buff.pos;
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
while ((n_words < max_rx) && spi_readable(obj)) {
while (spi_readable(obj)) {
if (spi_is_rx_complete(obj)) {
// Disregard as receive buffer is full
SPI_READ_RX(spi_base);

View File

@ -82,16 +82,13 @@ struct spi_s {
PinName pin_mosi;
PinName pin_sclk;
PinName pin_ssel;
//void (*vec)(void);
// Async transfer related fields
DMAUsage dma_usage;
int dma_chn_id_tx;
int dma_chn_id_rx;
uint32_t event;
//void (*irq_handler_tx_async)(void);
//void (*irq_handler_rx_async)(void);
uint32_t txrx_rmn; // Track tx/rx frames remaining in interrupt way
};
struct i2c_s {

View File

@ -394,6 +394,9 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx,
SPI_ENABLE_SYNC(spi_base);
// Initialize total SPI transfer frames
obj->spi.txrx_rmn = NU_MAX(tx_length, rx_length);
if (obj->spi.dma_usage == DMA_USAGE_NEVER) {
// Interrupt way
spi_master_write_asynch(obj, spi_fifo_depth(obj) / 2);
@ -654,16 +657,12 @@ static uint32_t spi_event_check(spi_t *obj)
static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
{
uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_tx = NU_MAX(tx_rmn, rx_rmn);
max_tx = NU_MIN(max_tx, tx_limit);
uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8;
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer) + bytes_per_word * obj->tx_buff.pos;
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
while ((n_words < max_tx) && spi_writeable(obj)) {
while (obj->spi.txrx_rmn && spi_writeable(obj)) {
if (spi_is_tx_complete(obj)) {
// Transmit dummy as transmit buffer is empty
SPI_WRITE_TX(spi_base, 0);
@ -686,6 +685,7 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
obj->tx_buff.pos ++;
}
n_words ++;
obj->spi.txrx_rmn --;
}
//Return the number of words that have been sent
@ -706,15 +706,12 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
static uint32_t spi_master_read_asynch(spi_t *obj)
{
uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_rx = NU_MAX(tx_rmn, rx_rmn);
uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8;
uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer) + bytes_per_word * obj->rx_buff.pos;
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
while ((n_words < max_rx) && spi_readable(obj)) {
while (spi_readable(obj)) {
if (spi_is_rx_complete(obj)) {
// Disregard as receive buffer is full
SPI_READ_RX(spi_base);

View File

@ -85,6 +85,7 @@ struct spi_s {
int dma_chn_id_tx;
int dma_chn_id_rx;
uint32_t event;
uint32_t txrx_rmn; // Track tx/rx frames remaining in interrupt way
uint32_t hdlr_async;
};

View File

@ -435,6 +435,9 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx,
SPI_ENABLE_SYNC(spi_base);
// Initialize total SPI transfer frames
obj->spi.txrx_rmn = NU_MAX(tx_length, rx_length);
if (obj->spi.dma_usage == DMA_USAGE_NEVER) {
// Interrupt way
spi_master_write_asynch(obj, NU_SPI_FIFO_DEPTH / 2);
@ -714,17 +717,13 @@ static uint32_t spi_event_check(spi_t *obj)
static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
{
uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_tx = NU_MAX(tx_rmn, rx_rmn);
max_tx = NU_MIN(max_tx, tx_limit);
uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8;
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer) + bytes_per_word * obj->tx_buff.pos;
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
uint32_t TX = (NU_MODSUBINDEX(obj->spi.spi) == 0) ? ((uint32_t) &spi_base->TX0) : ((uint32_t) &spi_base->TX1);
while ((n_words < max_tx) && spi_writeable(obj)) {
while (obj->spi.txrx_rmn && spi_writeable(obj)) {
if (spi_is_tx_complete(obj)) {
// Transmit dummy as transmit buffer is empty
M32(TX) = 0;
@ -748,6 +747,7 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
obj->tx_buff.pos ++;
}
n_words ++;
obj->spi.txrx_rmn --;
}
//Return the number of words that have been sent
@ -768,16 +768,13 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
static uint32_t spi_master_read_asynch(spi_t *obj)
{
uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_rx = NU_MAX(tx_rmn, rx_rmn);
uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8;
uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer) + bytes_per_word * obj->rx_buff.pos;
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
uint32_t RX = (NU_MODSUBINDEX(obj->spi.spi) == 0) ? ((uint32_t) &spi_base->RX0) : ((uint32_t) &spi_base->RX1);
while ((n_words < max_rx) && spi_readable(obj)) {
while (spi_readable(obj)) {
if (spi_is_rx_complete(obj)) {
// Disregard as receive buffer is full
M32(RX);

View File

@ -78,16 +78,13 @@ struct spi_s {
PinName pin_mosi;
PinName pin_sclk;
PinName pin_ssel;
//void (*vec)(void);
// Async transfer related fields
DMAUsage dma_usage;
int dma_chn_id_tx;
int dma_chn_id_rx;
uint32_t event;
//void (*irq_handler_tx_async)(void);
//void (*irq_handler_rx_async)(void);
uint32_t txrx_rmn; // Track tx/rx frames remaining in interrupt way
};
struct i2c_s {

View File

@ -387,6 +387,9 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx,
SPI_ENABLE_SYNC(spi_base);
// Initialize total SPI transfer frames
obj->spi.txrx_rmn = NU_MAX(tx_length, rx_length);
if (obj->spi.dma_usage == DMA_USAGE_NEVER) {
// Interrupt way
spi_master_write_asynch(obj, NU_SPI_FIFO_DEPTH / 2);
@ -645,16 +648,12 @@ static uint32_t spi_event_check(spi_t *obj)
static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
{
uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_tx = NU_MAX(tx_rmn, rx_rmn);
max_tx = NU_MIN(max_tx, tx_limit);
uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8;
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer) + bytes_per_word * obj->tx_buff.pos;
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
while ((n_words < max_tx) && spi_writeable(obj)) {
while (obj->spi.txrx_rmn && spi_writeable(obj)) {
if (spi_is_tx_complete(obj)) {
// Transmit dummy as transmit buffer is empty
SPI_WRITE_TX(spi_base, 0);
@ -678,6 +677,7 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
obj->tx_buff.pos ++;
}
n_words ++;
obj->spi.txrx_rmn --;
}
//Return the number of words that have been sent
@ -698,15 +698,12 @@ static uint32_t spi_master_write_asynch(spi_t *obj, uint32_t tx_limit)
static uint32_t spi_master_read_asynch(spi_t *obj)
{
uint32_t n_words = 0;
uint32_t tx_rmn = obj->tx_buff.length - obj->tx_buff.pos;
uint32_t rx_rmn = obj->rx_buff.length - obj->rx_buff.pos;
uint32_t max_rx = NU_MAX(tx_rmn, rx_rmn);
uint8_t data_width = spi_get_data_width(obj);
uint8_t bytes_per_word = (data_width + 7) / 8;
uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer) + bytes_per_word * obj->rx_buff.pos;
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
while ((n_words < max_rx) && spi_readable(obj)) {
while (spi_readable(obj)) {
if (spi_is_rx_complete(obj)) {
// Disregard as receive buffer is full
SPI_READ_RX(spi_base);