[NANO130] Fix SPI slave failed

pull/4631/head
ccli8 2017-04-20 13:13:39 +08:00
parent 71cd9c3b55
commit b219a3ee18
1 changed files with 40 additions and 19 deletions

View File

@ -43,7 +43,8 @@ struct nu_spi_var {
#endif #endif
}; };
// NOTE: NANO130 doesn't support relocating vector table. ISR vector passed into NVIC_SetVector() can only be weak symbol defined in startup_Nano100Series.c. // NOTE:
// NANO130: No support for relocating vector table. ISR vector passed into NVIC_SetVector() can only be weak symbol defined in startup_Nano100Series.c.
void SPI0_IRQHandler(void); void SPI0_IRQHandler(void);
void SPI1_IRQHandler(void); void SPI1_IRQHandler(void);
void SPI2_IRQHandler(void); void SPI2_IRQHandler(void);
@ -200,12 +201,13 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
// NOTE 1: All configurations should be ready before enabling SPI peripheral. // NOTE: All configurations should be ready before enabling SPI peripheral.
// NOTE 2: Re-configuration is allowed only as SPI peripheral is idle. // NOTE: Re-configuration is allowed only as SPI peripheral is idle.
// NOTE 3: On NANO130, SPI_CTL.GO_BUSY always reads as 1 in slave mode. Cannot use to judge busy or not. // NOTE:
if (! (spi_base->CTL & SPI_CTL_SLAVE_Msk)) { // NANO130, SPI_CTL.GO_BUSY always reads as 1 in slave/FIFO mode. So disable FIFO first.
while (SPI_IS_BUSY(spi_base)); SPI_DisableFIFO(spi_base);
} while (SPI_IS_BUSY(spi_base));
SPI_Open(spi_base, SPI_Open(spi_base,
slave ? SPI_SLAVE : SPI_MASTER, slave ? SPI_SLAVE : SPI_MASTER,
@ -214,8 +216,6 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
SPI_GetBusClock(spi_base)); SPI_GetBusClock(spi_base));
// NOTE: Hardcode to be MSB first. // NOTE: Hardcode to be MSB first.
SPI_SET_MSB_FIRST(spi_base); SPI_SET_MSB_FIRST(spi_base);
// NOTE: On NANO130, FIFO mode defaults to disabled in SPI_Open(), so place SPI_EnableFIFO() after SPI_Open().
SPI_EnableFIFO(spi_base, NU_SPI_FIFO_DEPTH / 2, NU_SPI_FIFO_DEPTH / 2);
if (! slave) { if (! slave) {
// Master // Master
@ -246,19 +246,29 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
spi_base->SSR &= ~SPI_SS1_ACTIVE_HIGH; spi_base->SSR &= ~SPI_SS1_ACTIVE_HIGH;
break; break;
} }
// NOTE:
// NANO130: Configure slave select signal to edge-trigger rather than level-trigger
spi_base->SSR |= SPI_SSR_SS_LTRIG_Msk;
} }
// NOTE:
// NANO130: FIFO mode defaults to disabled.
SPI_EnableFIFO(spi_base, NU_SPI_FIFO_DEPTH / 2, NU_SPI_FIFO_DEPTH / 2);
} }
void spi_frequency(spi_t *obj, int hz) void spi_frequency(spi_t *obj, int hz)
{ {
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
// NOTE: On NANO130, SPI_CTL.GO_BUSY always reads as 1 in slave mode. Cannot use to judge busy or not. // NANO130, SPI_CTL.GO_BUSY always reads as 1 in slave/FIFO mode. So disable FIFO first.
if (! (spi_base->CTL & SPI_CTL_SLAVE_Msk)) { SPI_DisableFIFO(spi_base);
while (SPI_IS_BUSY(spi_base)); while (SPI_IS_BUSY(spi_base));
}
SPI_SetBusClock((SPI_T *) NU_MODBASE(obj->spi.spi), hz); SPI_SetBusClock((SPI_T *) NU_MODBASE(obj->spi.spi), hz);
// NOTE:
// NANO130: FIFO mode defaults to disabled.
SPI_EnableFIFO(spi_base, NU_SPI_FIFO_DEPTH / 2, NU_SPI_FIFO_DEPTH / 2);
} }
@ -267,7 +277,9 @@ int spi_master_write(spi_t *obj, int value)
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
// NOTE: Data in receive FIFO can be read out via ICE. // NOTE: Data in receive FIFO can be read out via ICE.
// NOTE: On NANO130, not required as FIFO mode is enabled. // 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_TRIGGER(spi_base); //SPI_TRIGGER(spi_base);
// Wait for tx buffer empty // Wait for tx buffer empty
@ -286,7 +298,9 @@ int spi_master_write(spi_t *obj, int value)
#if DEVICE_SPISLAVE #if DEVICE_SPISLAVE
int spi_slave_receive(spi_t *obj) int spi_slave_receive(spi_t *obj)
{ {
// NOTE: On NANO130, not required as FIFO mode is enabled. // 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_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); //SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
//SPI_TRIGGER(spi_base); //SPI_TRIGGER(spi_base);
@ -297,7 +311,9 @@ int spi_slave_read(spi_t *obj)
{ {
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
// NOTE: On NANO130, not required as FIFO mode is enabled. // 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_TRIGGER(spi_base); //SPI_TRIGGER(spi_base);
// Wait for rx buffer full // Wait for rx buffer full
@ -311,7 +327,9 @@ void spi_slave_write(spi_t *obj, int value)
{ {
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
// NOTE: On NANO130, not required as FIFO mode is enabled. // 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_TRIGGER(spi_base); //SPI_TRIGGER(spi_base);
// Wait for tx buffer empty // Wait for tx buffer empty
@ -347,7 +365,9 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx,
spi_enable_event(obj, event, 1); spi_enable_event(obj, event, 1);
spi_buffer_set(obj, tx, tx_length, rx, rx_length); spi_buffer_set(obj, tx, tx_length, rx, rx_length);
// NOTE: On NANO130, not required as FIFO mode is enabled. // 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_TRIGGER(spi_base); //SPI_TRIGGER(spi_base);
if (obj->spi.dma_usage == DMA_USAGE_NEVER) { if (obj->spi.dma_usage == DMA_USAGE_NEVER) {
@ -594,7 +614,8 @@ static void spi_master_enable_interrupt(spi_t *obj, uint8_t enable, uint32_t mas
{ {
SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi); SPI_T *spi_base = (SPI_T *) NU_MODBASE(obj->spi.spi);
// NOTE: On NANO130, SPI_IE_MASK/SPI_STATUS_INTSTS_Msk are for unit transfer IE/EF. Don't get confused. // NOTE:
// NANO130: SPI_IE_MASK/SPI_STATUS_INTSTS_Msk are for unit transfer IE/EF. Don't get confused.
if (enable) { if (enable) {
//SPI_SET_SUSPEND_CYCLE(spi_base, 4); //SPI_SET_SUSPEND_CYCLE(spi_base, 4);
// Enable tx/rx FIFO threshold interrupt // Enable tx/rx FIFO threshold interrupt