diff --git a/targets/TARGET_NUVOTON/TARGET_M451/spi_api.c b/targets/TARGET_NUVOTON/TARGET_M451/spi_api.c index f07a935976..89f011eb3a 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/spi_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/spi_api.c @@ -161,6 +161,11 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel obj->spi.event = 0; obj->spi.dma_chn_id_tx = DMA_ERROR_OUT_OF_CHANNELS; obj->spi.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS; + + /* NOTE: We use vector to judge if asynchronous transfer is on-going (spi_active). + * At initial time, asynchronous transfer is not on-going and so vector must + * be cleared to zero for correct judgement. */ + NVIC_SetVector(modinit->irq_n, 0); #endif // Mark this module to be inited. @@ -231,8 +236,9 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) spi_base->SSCTL &= ~SPI_SSCTL_SSACTPOL_Msk; } - // NOTE: M451's SPI_Open() will enable SPI transfer (SPI_CTL_SPIEN_Msk). This will violate judgement of spi_active(). Disable it. - SPI_DISABLE_SYNC(spi_base); + /* NOTE: M451's/M480's/M2351's SPI_Open() will enable SPI transfer (SPI_CTL_SPIEN_Msk). + * We cannot use SPI_CTL_SPIEN_Msk for judgement of spi_active(). + * Judge with vector instead. */ } void spi_frequency(spi_t *obj, int hz) @@ -259,9 +265,9 @@ int spi_master_write(spi_t *obj, int value) // Wait for rx buffer full while (! spi_readable(obj)); int value2 = SPI_READ_RX(spi_base); - - SPI_DISABLE_SYNC(spi_base); - + + /* We don't call SPI_DISABLE_SYNC here for performance. */ + return value2; } @@ -477,20 +483,14 @@ uint32_t spi_irq_handler_asynch(spi_t *obj) uint8_t spi_active(spi_t *obj) { - SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - // FIXME - /* - if ((obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) - || (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) ){ - return 1; - } else { - // interrupts are disabled, all transaction have been completed - // TODO: checking rx fifo, it reports data eventhough RFDF is not set - return DSPI_HAL_GetIntMode(obj->spi.address, kDspiRxFifoDrainRequest); - }*/ - - //return SPI_IS_BUSY(spi_base); - return (spi_base->CTL & SPI_CTL_SPIEN_Msk); + const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); + MBED_ASSERT(modinit != NULL); + MBED_ASSERT(modinit->modname == (int) obj->spi.spi); + + /* Vector will be cleared when asynchronous transfer is finished or aborted. + Use it to judge if asynchronous transfer is on-going. */ + uint32_t vec = NVIC_GetVector(modinit->irq_n); + return vec ? 1 : 0; } static int spi_writeable(spi_t * obj) @@ -525,8 +525,8 @@ static void spi_enable_vector_interrupt(spi_t *obj, uint32_t handler, uint8_t en NVIC_EnableIRQ(modinit->irq_n); } else { - //NVIC_SetVector(modinit->irq_n, handler); NVIC_DisableIRQ(modinit->irq_n); + NVIC_SetVector(modinit->irq_n, 0); } } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/spi_api.c b/targets/TARGET_NUVOTON/TARGET_M480/spi_api.c index 035c1c8663..ce18e976a2 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/spi_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/spi_api.c @@ -170,6 +170,11 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel obj->spi.event = 0; obj->spi.dma_chn_id_tx = DMA_ERROR_OUT_OF_CHANNELS; obj->spi.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS; + + /* NOTE: We use vector to judge if asynchronous transfer is on-going (spi_active). + * At initial time, asynchronous transfer is not on-going and so vector must + * be cleared to zero for correct judgement. */ + NVIC_SetVector(modinit->irq_n, 0); #endif // Mark this module to be inited. @@ -236,8 +241,9 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) spi_base->SSCTL &= ~SPI_SSCTL_SSACTPOL_Msk; } - // NOTE: M451's/M480's SPI_Open() will enable SPI transfer (SPI_CTL_SPIEN_Msk). This will violate judgement of spi_active(). Disable it. - SPI_DISABLE_SYNC(spi_base); + /* NOTE: M451's/M480's/M2351's SPI_Open() will enable SPI transfer (SPI_CTL_SPIEN_Msk). + * We cannot use SPI_CTL_SPIEN_Msk for judgement of spi_active(). + * Judge with vector instead. */ } void spi_frequency(spi_t *obj, int hz) @@ -265,7 +271,7 @@ int spi_master_write(spi_t *obj, int value) while (! spi_readable(obj)); int value2 = SPI_READ_RX(spi_base); - SPI_DISABLE_SYNC(spi_base); + /* We don't call SPI_DISABLE_SYNC here for performance. */ return value2; } @@ -479,9 +485,14 @@ uint32_t spi_irq_handler_asynch(spi_t *obj) uint8_t spi_active(spi_t *obj) { - SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); + const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); + MBED_ASSERT(modinit != NULL); + MBED_ASSERT(modinit->modname == (int) obj->spi.spi); - return (spi_base->CTL & SPI_CTL_SPIEN_Msk); + /* Vector will be cleared when asynchronous transfer is finished or aborted. + Use it to judge if asynchronous transfer is on-going. */ + uint32_t vec = NVIC_GetVector(modinit->irq_n); + return vec ? 1 : 0; } static int spi_writeable(spi_t * obj) @@ -515,6 +526,7 @@ static void spi_enable_vector_interrupt(spi_t *obj, uint32_t handler, uint8_t en NVIC_EnableIRQ(modinit->irq_n); } else { NVIC_DisableIRQ(modinit->irq_n); + NVIC_SetVector(modinit->irq_n, 0); } } diff --git a/targets/TARGET_NUVOTON/TARGET_NANO100/spi_api.c b/targets/TARGET_NUVOTON/TARGET_NANO100/spi_api.c index f7209c4a65..e8c7c58e2f 100644 --- a/targets/TARGET_NUVOTON/TARGET_NANO100/spi_api.c +++ b/targets/TARGET_NUVOTON/TARGET_NANO100/spi_api.c @@ -182,6 +182,16 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel obj->spi.event = 0; obj->spi.dma_chn_id_tx = DMA_ERROR_OUT_OF_CHANNELS; obj->spi.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS; + + /* NOTE: We use vector to judge if asynchronous transfer is on-going (spi_active). + * At initial time, asynchronous transfer is not on-going and so vector must + * be cleared to zero for correct judgement. */ + /* NOTE: On NANO130, vector table is fixed in ROM and cannot be modified. */ +#if 0 + NVIC_SetVector(modinit->irq_n, 0); +#else + obj->spi.hdlr_async = 0; +#endif #endif // Mark this module to be inited. @@ -266,6 +276,10 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) // NANO130: Configure slave select signal to edge-trigger rather than level-trigger spi_base->SSR |= SPI_SSR_SS_LTRIG_Msk; } + + /* NOTE: M451's/M480's/M2351's SPI_Open() will enable SPI transfer (SPI_CTL_SPIEN_Msk). + * We cannot use SPI_CTL_SPIEN_Msk for judgement of spi_active(). + * Judge with vector instead. */ } void spi_frequency(spi_t *obj, int hz) @@ -297,7 +311,9 @@ int spi_master_write(spi_t *obj, int value) 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); - + + /* We don't call SPI_DISABLE_SYNC here for performance. */ + return value2; } @@ -511,9 +527,19 @@ uint32_t spi_irq_handler_asynch(spi_t *obj) uint8_t spi_active(spi_t *obj) { - SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - - return SPI_IS_BUSY(spi_base); + const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); + MBED_ASSERT(modinit != NULL); + MBED_ASSERT(modinit->modname == (int) obj->spi.spi); + + /* Vector will be cleared when asynchronous transfer is finished or aborted. + Use it to judge if asynchronous transfer is on-going. */ + /* NOTE: On NANO130, vector table is fixed in ROM and cannot be modified. */ +#if 0 + uint32_t vec = NVIC_GetVector(modinit->irq_n); + return vec ? 1 : 0; +#else + return obj->spi.hdlr_async ? 1 : 0; +#endif } void SPI0_IRQHandler(void) @@ -567,13 +593,20 @@ static void spi_enable_vector_interrupt(spi_t *obj, uint32_t handler, uint8_t en if (enable) { var->obj = obj; obj->spi.hdlr_async = handler; + /* NOTE: On NANO130, vector table is fixed in ROM and cannot be modified. */ +#if 0 NVIC_SetVector(modinit->irq_n, (uint32_t) var->vec); +#endif NVIC_EnableIRQ(modinit->irq_n); } else { NVIC_DisableIRQ(modinit->irq_n); + /* NOTE: On NANO130, vector table is fixed in ROM and cannot be modified. */ +#if 0 + NVIC_SetVector(modinit->irq_n, 0); +#endif var->obj = NULL; - obj->spi.hdlr_async = handler; + obj->spi.hdlr_async = 0; } } diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/spi_api.c b/targets/TARGET_NUVOTON/TARGET_NUC472/spi_api.c index 5b063782ca..cf2a75f06d 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/spi_api.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/spi_api.c @@ -165,6 +165,11 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel obj->spi.event = 0; obj->spi.dma_chn_id_tx = DMA_ERROR_OUT_OF_CHANNELS; obj->spi.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS; + + /* NOTE: We use vector to judge if asynchronous transfer is on-going (spi_active). + * At initial time, asynchronous transfer is not on-going and so vector must + * be cleared to zero for correct judgement. */ + NVIC_SetVector(modinit->irq_n, 0); #endif // Mark this module to be inited. @@ -236,9 +241,10 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) spi_base->SSCTL &= ~SPI_SSCTL_SSACTPOL_Msk; // NOTE: SPI_SS0 is defined as the slave select input in Slave mode. } - - // NOTE: M451's/M480's SPI_Open() will enable SPI transfer (SPI_CTL_SPIEN_Msk). This will violate judgement of spi_active(). Disable it. - SPI_DISABLE_SYNC(spi_base); + + /* NOTE: M451's/M480's/M2351's SPI_Open() will enable SPI transfer (SPI_CTL_SPIEN_Msk). + * We cannot use SPI_CTL_SPIEN_Msk for judgement of spi_active(). + * Judge with vector instead. */ } void spi_frequency(spi_t *obj, int hz) @@ -265,9 +271,9 @@ int spi_master_write(spi_t *obj, int value) // Wait for rx buffer full while (! spi_readable(obj)); int value2 = SPI_READ_RX(spi_base); - - SPI_DISABLE_SYNC(spi_base); - + + /* We don't call SPI_DISABLE_SYNC here for performance. */ + return value2; } @@ -479,20 +485,14 @@ uint32_t spi_irq_handler_asynch(spi_t *obj) uint8_t spi_active(spi_t *obj) { - SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - // FIXME - /* - if ((obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) - || (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) ){ - return 1; - } else { - // interrupts are disabled, all transaction have been completed - // TODO: checking rx fifo, it reports data eventhough RFDF is not set - return DSPI_HAL_GetIntMode(obj->spi.address, kDspiRxFifoDrainRequest); - }*/ - - //return SPI_IS_BUSY(spi_base); - return (spi_base->CTL & SPI_CTL_SPIEN_Msk); + const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); + MBED_ASSERT(modinit != NULL); + MBED_ASSERT(modinit->modname == (int) obj->spi.spi); + + /* Vector will be cleared when asynchronous transfer is finished or aborted. + Use it to judge if asynchronous transfer is on-going. */ + uint32_t vec = NVIC_GetVector(modinit->irq_n); + return vec ? 1 : 0; } static int spi_writeable(spi_t * obj) @@ -527,8 +527,8 @@ static void spi_enable_vector_interrupt(spi_t *obj, uint32_t handler, uint8_t en NVIC_EnableIRQ(modinit->irq_n); } else { - //NVIC_SetVector(modinit->irq_n, handler); NVIC_DisableIRQ(modinit->irq_n); + NVIC_SetVector(modinit->irq_n, 0); } }