mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
Diff: targets/TARGET_NUVOTON/TARGET_M451/spi_api.c
- Revision:
- 186:707f6e361f3e
- Parent:
- 176:447f873cad2f
--- a/targets/TARGET_NUVOTON/TARGET_M451/spi_api.c Thu Apr 19 17:12:19 2018 +0100 +++ b/targets/TARGET_NUVOTON/TARGET_M451/spi_api.c Fri Jun 22 16:45:37 2018 +0100 @@ -60,6 +60,34 @@ #endif }; +/* Synchronous version of SPI_ENABLE()/SPI_DISABLE() macros + * + * The SPI peripheral clock is asynchronous with the system clock. In order to make sure the SPI + * control logic is enabled/disabled, this bit indicates the real status of SPI controller. + * + * NOTE: All configurations shall be ready before calling SPI_ENABLE_SYNC(). + * NOTE: Before changing the configurations of SPIx_CTL, SPIx_CLKDIV, SPIx_SSCTL and SPIx_FIFOCTL registers, + * user shall clear the SPIEN (SPIx_CTL[0]) and confirm the SPIENSTS (SPIx_STATUS[15]) is 0 + * (by SPI_DISABLE_SYNC here). + */ +__STATIC_INLINE void SPI_ENABLE_SYNC(SPI_T *spi_base) +{ + if (! (spi_base->CTL & SPI_CTL_SPIEN_Msk)) { + SPI_ENABLE(spi_base); + } + while (! (spi_base->STATUS & SPI_STATUS_SPIENSTS_Msk)); +} +__STATIC_INLINE void SPI_DISABLE_SYNC(SPI_T *spi_base) +{ + if (spi_base->CTL & SPI_CTL_SPIEN_Msk) { + // NOTE: SPI H/W may get out of state without the busy check. + while (SPI_IS_BUSY(spi_base)); + + SPI_DISABLE(spi_base); + } + while (spi_base->STATUS & SPI_STATUS_SPIENSTS_Msk); +} + #if DEVICE_SPI_ASYNCH static void spi_enable_vector_interrupt(spi_t *obj, uint32_t handler, uint8_t enable); static void spi_master_enable_interrupt(spi_t *obj, uint8_t enable); @@ -84,7 +112,7 @@ {SPI_0, SPI0_MODULE, CLK_CLKSEL2_SPI0SEL_PCLK0, MODULE_NoMsk, SPI0_RST, SPI0_IRQn, &spi0_var}, {SPI_1, SPI1_MODULE, CLK_CLKSEL2_SPI1SEL_PCLK1, MODULE_NoMsk, SPI1_RST, SPI1_IRQn, &spi1_var}, {SPI_2, SPI2_MODULE, CLK_CLKSEL2_SPI2SEL_PCLK0, MODULE_NoMsk, SPI2_RST, SPI2_IRQn, &spi2_var}, - + {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL} }; @@ -101,38 +129,37 @@ const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); MBED_ASSERT(modinit != NULL); - MBED_ASSERT(modinit->modname == obj->spi.spi); - + MBED_ASSERT(modinit->modname == (int) obj->spi.spi); + // Reset this module SYS_ResetModule(modinit->rsetidx); - + // Select IP clock source CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv); // Enable IP clock CLK_EnableModuleClock(modinit->clkidx); - //SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - pinmap_pinout(mosi, PinMap_SPI_MOSI); pinmap_pinout(miso, PinMap_SPI_MISO); pinmap_pinout(sclk, PinMap_SPI_SCLK); pinmap_pinout(ssel, PinMap_SPI_SSEL); - + obj->spi.pin_mosi = mosi; obj->spi.pin_miso = miso; obj->spi.pin_sclk = sclk; obj->spi.pin_ssel = ssel; - - // Configure the SPI data format and frequency - //spi_format(obj, 8, 0, SPI_MSB); // 8 bits, mode 0 - //spi_frequency(obj, 1000000); - + #if DEVICE_SPI_ASYNCH obj->spi.dma_usage = DMA_USAGE_NEVER; 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. @@ -154,33 +181,29 @@ #endif SPI_Close((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 == obj->spi.spi); - + MBED_ASSERT(modinit->modname == (int) obj->spi.spi); + SPI_DisableInt(((SPI_T *) NU_MODBASE(obj->spi.spi)), (SPI_FIFO_RXOV_INT_MASK | SPI_FIFO_RXTH_INT_MASK | SPI_FIFO_TXTH_INT_MASK)); NVIC_DisableIRQ(modinit->irq_n); - + // Disable IP clock CLK_DisableModuleClock(modinit->clkidx); - - //((struct nu_spi_var *) modinit->var)->obj = NULL; - + // Mark this module to be deinited. int i = modinit - spi_modinit_tab; spi_modinit_mask &= ~(1 << i); } + void spi_format(spi_t *obj, int bits, int mode, int slave) { MBED_ASSERT(bits >= NU_SPI_FRAME_MIN && bits <= NU_SPI_FRAME_MAX); - + SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - - // NOTE 1: All configurations should be ready before enabling SPI peripheral. - // NOTE 2: Re-configuration is allowed only as SPI peripheral is idle. - while (SPI_IS_BUSY(spi_base)); - SPI_DISABLE(spi_base); + + SPI_DISABLE_SYNC(spi_base); SPI_Open(spi_base, slave ? SPI_SLAVE : SPI_MASTER, @@ -193,7 +216,7 @@ if (! slave) { // Master if (obj->spi.pin_ssel != NC) { - // Configure SS as low active. + // Configure SS as low active. SPI_EnableAutoSS(spi_base, SPI_SS, SPI_SS_ACTIVE_LOW); } else { @@ -206,16 +229,16 @@ 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(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) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - - while (SPI_IS_BUSY(spi_base)); - SPI_DISABLE(spi_base); + + SPI_DISABLE_SYNC(spi_base); SPI_SetBusClock((SPI_T *) NU_MODBASE(obj->spi.spi), hz); } @@ -224,10 +247,10 @@ int spi_master_write(spi_t *obj, int value) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + // NOTE: Data in receive FIFO can be read out via ICE. - SPI_ENABLE(spi_base); - + SPI_ENABLE_SYNC(spi_base); + // Wait for tx buffer empty while(! spi_writeable(obj)); SPI_WRITE_TX(spi_base, value); @@ -235,9 +258,9 @@ // Wait for rx buffer full while (! spi_readable(obj)); int value2 = SPI_READ_RX(spi_base); - - SPI_DISABLE(spi_base); - + + /* We don't call SPI_DISABLE_SYNC here for performance. */ + return value2; } @@ -260,18 +283,18 @@ int spi_slave_receive(spi_t *obj) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - - SPI_ENABLE(spi_base); - + + SPI_ENABLE_SYNC(spi_base); + return spi_readable(obj); }; int spi_slave_read(spi_t *obj) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - - SPI_ENABLE(spi_base); - + + SPI_ENABLE_SYNC(spi_base); + // Wait for rx buffer full while (! spi_readable(obj)); int value = SPI_READ_RX(spi_base); @@ -281,9 +304,9 @@ void spi_slave_write(spi_t *obj, int value) { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - - SPI_ENABLE(spi_base); - + + SPI_ENABLE_SYNC(spi_base); + // Wait for tx buffer empty while(! spi_writeable(obj)); SPI_WRITE_TX(spi_base, value); @@ -293,7 +316,6 @@ #if DEVICE_SPI_ASYNCH void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint) { - //MBED_ASSERT(bits >= NU_SPI_FRAME_MIN && bits <= NU_SPI_FRAME_MAX); SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); SPI_SET_DATA_WIDTH(spi_base, bit_width); @@ -311,13 +333,13 @@ dma_channel_free(obj->spi.dma_chn_id_rx); obj->spi.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS; } - + // SPI IRQ is necessary for both interrupt way and DMA way spi_enable_event(obj, event, 1); spi_buffer_set(obj, tx, tx_length, rx, rx_length); - - SPI_ENABLE(spi_base); - + + SPI_ENABLE_SYNC(spi_base); + if (obj->spi.dma_usage == DMA_USAGE_NEVER) { // Interrupt way spi_master_write_asynch(obj, NU_SPI_FIFO_DEPTH / 2); @@ -327,10 +349,10 @@ // DMA way const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); MBED_ASSERT(modinit != NULL); - MBED_ASSERT(modinit->modname == obj->spi.spi); - + MBED_ASSERT(modinit->modname == (int) obj->spi.spi); + PDMA_T *pdma_base = dma_modbase(); - + // Configure tx DMA pdma_base->CHCTL |= 1 << obj->spi.dma_chn_id_tx; // Enable this DMA channel PDMA_SetTransferMode(obj->spi.dma_chn_id_tx, @@ -354,7 +376,7 @@ PDMA_INT_TRANS_DONE); // Interrupt type // Register DMA event handler dma_set_handler(obj->spi.dma_chn_id_tx, (uint32_t) spi_dma_handler_tx, (uint32_t) obj, DMA_EVENT_ALL); - + // Configure rx DMA pdma_base->CHCTL |= 1 << obj->spi.dma_chn_id_rx; // Enable this DMA channel PDMA_SetTransferMode(obj->spi.dma_chn_id_rx, @@ -378,13 +400,34 @@ PDMA_INT_TRANS_DONE); // Interrupt type // Register DMA event handler dma_set_handler(obj->spi.dma_chn_id_rx, (uint32_t) spi_dma_handler_rx, (uint32_t) obj, DMA_EVENT_ALL); - - // Start tx/rx DMA transfer - spi_enable_vector_interrupt(obj, handler, 1); - // NOTE: It is safer to start rx DMA first and then tx DMA. Otherwise, receive FIFO is subject to overflow by tx DMA. - SPI_TRIGGER_RX_PDMA(((SPI_T *) NU_MODBASE(obj->spi.spi))); - SPI_TRIGGER_TX_PDMA(((SPI_T *) NU_MODBASE(obj->spi.spi))); - spi_master_enable_interrupt(obj, 1); + + /* Start tx/rx DMA transfer + * + * If we have both PDMA and SPI interrupts enabled and PDMA priority is lower than SPI priority, + * we would trap in SPI interrupt handler endlessly with the sequence: + * + * 1. PDMA TX transfer done interrupt occurs and is well handled. + * 2. SPI RX FIFO threshold interrupt occurs. Trap here because PDMA RX transfer done interrupt doesn't get handled. + * 3. PDMA RX transfer done interrupt occurs but it cannot be handled due to above. + * + * To fix it, we don't enable SPI TX/RX threshold interrupts but keep SPI vector handler set to be called + * in PDMA TX/RX transfer done interrupt handlers (spi_dma_handler_tx/spi_dma_handler_rx). + */ + NVIC_SetVector(modinit->irq_n, handler); + + /* Order to enable PDMA TX/RX functions + * + * H/W spec: In SPI Master mode with full duplex transfer, if both TX and RX PDMA functions are + * enabled, RX PDMA function cannot be enabled prior to TX PDMA function. User can enable + * TX PDMA function firstly or enable both functions simultaneously. + * Per real test, it is safer to start RX PDMA first and then TX PDMA. Otherwise, receive FIFO is + * subject to overflow by TX DMA. + * + * With the above conflicts, we enable PDMA TX/RX functions simultaneously. + */ + spi_base->PDMACTL |= (SPI_PDMACTL_TXPDMAEN_Msk | SPI_PDMACTL_RXPDMAEN_Msk); + + /* Don't enable SPI TX/RX threshold interrupts as commented above */ } } @@ -398,38 +441,35 @@ { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); PDMA_T *pdma_base = dma_modbase(); - + if (obj->spi.dma_usage != DMA_USAGE_NEVER) { // Receive FIFO Overrun in case of tx length > rx length on DMA way if (spi_base->STATUS & SPI_STATUS_RXOVIF_Msk) { spi_base->STATUS = SPI_STATUS_RXOVIF_Msk; } - + if (obj->spi.dma_chn_id_tx != DMA_ERROR_OUT_OF_CHANNELS) { PDMA_DisableInt(obj->spi.dma_chn_id_tx, PDMA_INT_TRANS_DONE); - // FIXME: On NUC472, next PDMA transfer will fail with PDMA_STOP() called. Cause is unknown. - //PDMA_STOP(obj->spi.dma_chn_id_tx); + // NOTE: On NUC472, next PDMA transfer will fail with PDMA_STOP() called. Cause is unknown. pdma_base->CHCTL &= ~(1 << obj->spi.dma_chn_id_tx); } SPI_DISABLE_TX_PDMA(((SPI_T *) NU_MODBASE(obj->spi.spi))); - + if (obj->spi.dma_chn_id_rx != DMA_ERROR_OUT_OF_CHANNELS) { PDMA_DisableInt(obj->spi.dma_chn_id_rx, PDMA_INT_TRANS_DONE); - // FIXME: On NUC472, next PDMA transfer will fail with PDMA_STOP() called. Cause is unknown. - //PDMA_STOP(obj->spi.dma_chn_id_rx); + // NOTE: On NUC472, next PDMA transfer will fail with PDMA_STOP() called. Cause is unknown. pdma_base->CHCTL &= ~(1 << obj->spi.dma_chn_id_rx); } SPI_DISABLE_RX_PDMA(((SPI_T *) NU_MODBASE(obj->spi.spi))); } - + // Necessary for both interrupt way and DMA way spi_enable_vector_interrupt(obj, 0, 0); spi_master_enable_interrupt(obj, 0); - // FIXME: SPI H/W may get out of state without the busy check. - while (SPI_IS_BUSY(spi_base)); - SPI_DISABLE(spi_base); - + /* Necessary for accessing FIFOCTL below */ + SPI_DISABLE_SYNC(spi_base); + SPI_ClearRxFIFO(spi_base); SPI_ClearTxFIFO(spi_base); } @@ -454,26 +494,19 @@ 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) { // Receive FIFO must not be full to avoid receive FIFO overflow on next transmit/receive - //return (! SPI_GET_TX_FIFO_FULL_FLAG(((SPI_T *) NU_MODBASE(obj->spi.spi)))) && (SPI_GET_RX_FIFO_COUNT(((SPI_T *) NU_MODBASE(obj->spi.spi))) < NU_SPI_FIFO_DEPTH); return (! SPI_GET_TX_FIFO_FULL_FLAG(((SPI_T *) NU_MODBASE(obj->spi.spi)))); } @@ -483,7 +516,7 @@ } static void spi_enable_event(spi_t *obj, uint32_t event, uint8_t enable) -{ +{ obj->spi.event &= ~SPI_EVENT_ALL; obj->spi.event |= (event & SPI_EVENT_ALL); if (event & SPI_EVENT_RX_OVERFLOW) { @@ -495,22 +528,22 @@ { const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); MBED_ASSERT(modinit != NULL); - MBED_ASSERT(modinit->modname == obj->spi.spi); - + MBED_ASSERT(modinit->modname == (int) obj->spi.spi); + if (enable) { NVIC_SetVector(modinit->irq_n, handler); NVIC_EnableIRQ(modinit->irq_n); } else { - //NVIC_SetVector(modinit->irq_n, handler); NVIC_DisableIRQ(modinit->irq_n); + NVIC_SetVector(modinit->irq_n, 0); } } static void spi_master_enable_interrupt(spi_t *obj, uint8_t enable) -{ +{ SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + if (enable) { // For SPI0, it could be 0 ~ 7. For SPI1 and SPI2, it could be 0 ~ 3. if (spi_base == (SPI_T *) SPI0_BASE) { @@ -519,7 +552,7 @@ else { SPI_SetFIFO(spi_base, 2, 2); } - //SPI_SET_SUSPEND_CYCLE(spi_base, 4); + // Enable tx/rx FIFO threshold interrupt SPI_EnableInt(spi_base, SPI_FIFO_RXTH_INT_MASK | SPI_FIFO_TXTH_INT_MASK); } @@ -532,16 +565,16 @@ { SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); uint32_t event = 0; - + if (obj->spi.dma_usage == DMA_USAGE_NEVER) { uint32_t n_rec = spi_master_read_asynch(obj); spi_master_write_asynch(obj, n_rec); } - + if (spi_is_tx_complete(obj) && spi_is_rx_complete(obj)) { event |= SPI_EVENT_COMPLETE; } - + // Receive FIFO Overrun if (spi_base->STATUS & SPI_STATUS_RXOVIF_Msk) { spi_base->STATUS = SPI_STATUS_RXOVIF_Msk; @@ -550,7 +583,7 @@ event |= SPI_EVENT_RX_OVERFLOW; } } - + // Receive Time-Out if (spi_base->STATUS & SPI_STATUS_RXTOIF_Msk) { spi_base->STATUS = SPI_STATUS_RXTOIF_Msk; @@ -561,7 +594,7 @@ spi_base->STATUS = SPI_STATUS_TXUFIF_Msk; event |= SPI_EVENT_ERROR; } - + return event; } @@ -583,7 +616,7 @@ 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)) { if (spi_is_tx_complete(obj)) { // Transmit dummy as transmit buffer is empty @@ -604,12 +637,12 @@ tx += 1; break; } - + obj->tx_buff.pos ++; } n_words ++; } - + //Return the number of words that have been sent return n_words; } @@ -635,7 +668,7 @@ 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)) { if (spi_is_rx_complete(obj)) { // Disregard as receive buffer is full @@ -659,12 +692,12 @@ *rx ++ = SPI_READ_RX(spi_base); break; } - + obj->rx_buff.pos ++; } n_words ++; } - + // Return the number of words received return n_words; } @@ -690,12 +723,12 @@ if (*dma_ch_rx == DMA_ERROR_OUT_OF_CHANNELS) { *dma_ch_rx = dma_channel_allocate(DMA_CAP_NONE); } - + if (*dma_ch_tx == DMA_ERROR_OUT_OF_CHANNELS || *dma_ch_rx == DMA_ERROR_OUT_OF_CHANNELS) { *dma_usage = DMA_USAGE_NEVER; } } - + if (*dma_usage == DMA_USAGE_NEVER) { dma_channel_free(*dma_ch_tx); *dma_ch_tx = DMA_ERROR_OUT_OF_CHANNELS; @@ -705,22 +738,20 @@ } static uint8_t spi_get_data_width(spi_t *obj) -{ +{ SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); - + uint32_t data_width = ((spi_base->CTL & SPI_CTL_DWIDTH_Msk) >> SPI_CTL_DWIDTH_Pos); if (data_width == 0) { data_width = 32; } - + return data_width; } static int spi_is_tx_complete(spi_t *obj) { - // ???: Exclude tx fifo empty check due to no such interrupt on DMA way return (obj->tx_buff.pos == obj->tx_buff.length); - //return (obj->tx_buff.pos == obj->tx_buff.length && SPI_GET_TX_FIFO_EMPTY_FLAG(((SPI_T *) NU_MODBASE(obj->spi.spi)))); } static int spi_is_rx_complete(spi_t *obj) @@ -731,22 +762,22 @@ static void spi_dma_handler_tx(uint32_t id, uint32_t event_dma) { spi_t *obj = (spi_t *) id; - - // FIXME: Pass this error to caller + + // TODO: Pass this error to caller if (event_dma & DMA_EVENT_ABORT) { } // Expect SPI IRQ will catch this transfer done event if (event_dma & DMA_EVENT_TRANSFER_DONE) { obj->tx_buff.pos = obj->tx_buff.length; } - // FIXME: Pass this error to caller + // TODO: Pass this error to caller if (event_dma & DMA_EVENT_TIMEOUT) { } - + const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); MBED_ASSERT(modinit != NULL); - MBED_ASSERT(modinit->modname == obj->spi.spi); - + MBED_ASSERT(modinit->modname == (int) obj->spi.spi); + void (*vec)(void) = (void (*)(void)) NVIC_GetVector(modinit->irq_n); vec(); } @@ -754,22 +785,22 @@ static void spi_dma_handler_rx(uint32_t id, uint32_t event_dma) { spi_t *obj = (spi_t *) id; - - // FIXME: Pass this error to caller + + // TODO: Pass this error to caller if (event_dma & DMA_EVENT_ABORT) { } // Expect SPI IRQ will catch this transfer done event if (event_dma & DMA_EVENT_TRANSFER_DONE) { obj->rx_buff.pos = obj->rx_buff.length; } - // FIXME: Pass this error to caller + // TODO: Pass this error to caller if (event_dma & DMA_EVENT_TIMEOUT) { } - + const struct nu_modinit_s *modinit = get_modinit(obj->spi.spi, spi_modinit_tab); MBED_ASSERT(modinit != NULL); - MBED_ASSERT(modinit->modname == obj->spi.spi); - + MBED_ASSERT(modinit->modname == (int) obj->spi.spi); + void (*vec)(void) = (void (*)(void)) NVIC_GetVector(modinit->irq_n); vec(); }