Hello,
I'm having a problem with the SPI 1 reception in slave mode on the C6747. I'm not using BIOS.
The SPI is set up in 4-pin mode with SPIx_SCS[n]. The master uses a SCLK frequency of 128 kbps. Small packets (< 10 bytes) are sent frequently to the DSP (every 4 or 5 ms) by the master. The DSP receives each byte and the Rx ISR is executed. The ISR examines each byte and prepares the next Tx byte before the next master clock edge arrives. At this clock frequency, there is 3.9 us (half the clock period) to write the Tx byte to the SPI DATA register. To ensure the lowest ISR latency, the ISR function and associated global variables are placed in L2 RAM. Both L1P and L1D caches are enabled.
To view that the ISR is called when the DSP is running, I toggle a port pin and visualise the state on a scope.
This works fine for the first 10 or 15 seconds but after that no more SPI Rx interrupts are triggered. When debugging with an emulator, I halt after this has happened and check the SPIFLG register: the data overrun flag OVRNINTFLG is asserted.
I've tried many strategies in the Rx ISR, the following runs the longest before the SPI Rx IRQ stops triggering. Here are the first lines of my ISR (the rest are for preparing the Tx byte):
Uint32 lReg;
Uint8 lRxData;
Uint8 lErr;
lErr = 0;
while (1)
{
/* check error
flags in SPIFLG */
lReg =
gCommDev->SPIBUF;
/* clear rx
flags */
gCommDev->SPIFLG = (CSL_SPI_SPIFLG_RXINTFLG_MASK |
CSL_SPI_SPIFLG_DLENERRFLG_MASK
|
CSL_SPI_SPIFLG_OVRNINTFLG_MASK);
/* if rx
overrun, must read buffer again to empty RXBUF and SPIBUF */
if (lReg &
CSL_SPI_SPIBUF_RXOVR_MASK) {
lRxData =
gCommDev->SPIBUF;
}
if (!(lReg &
(CSL_SPI_SPIBUF_RXOVR_MASK |
CSL_SPI_SPIBUF_DLENERR_MASK))) {
lRxData = (Uint8)lReg;
break;
}
lErr = 1;
}
After reset, the SPI 1 is configured as so:
CSL_SpiRegsOvly gCommDev = (CSL_SpiRegsOvly)CSL_SPI_1_REGS;
/* bring the SPI out of reset state */
CSL_FINST(gCommDev->SPIGCR0, SPI_SPIGCR0_RESET, OUT_OF_RESET);
/* all SPI registers now have their default values */
/* set the preconfigure data format as 0 */
gCommDev->SPIDAT1 = CSL_FMKT(SPI_SPIDAT1_DFSEL, FORMAT0);
/* disable interrupts */
gCommDev->SPIINT0 = CSL_FMKT(SPI_SPIINT0_RXINTENA, DISABLE);
gCommDev->SPIGCR1 = CSL_SPI_SPIPC0_RESETVAL;
gCommDev->SPIFLG = ~0; /* clear flags */
gCommDev->SPILVL = CSL_FMKT(SPI_SPILVL_RXINTLVL, INT1) |
CSL_FMKT(SPI_SPILVL_OVRNINTLVL, INT1) |
CSL_FMKT(SPI_SPILVL_DLENERRLVL, INT1);
gCommDev->SPIINT0 = CSL_FMKT(SPI_SPIINT0_RXINTENA, ENABLE) |
CSL_FMKT(SPI_SPIINT0_OVRNINTENA, ENABLE) |
CSL_FMKT(SPI_SPIINT0_DLENERRENA, ENABLE);
gCommDev->SPIPC0 = CSL_FMKT(SPI_SPIPC0_CLKFUN, SPI) |
CSL_FMKT(SPI_SPIPC0_SIMOFUN, SPI) |
CSL_FMKT(SPI_SPIPC0_SOMIFUN, SPI) |
CSL_FMKT(SPI_SPIPC0_SCS0FUN0, SPI);
gCommDev->SPIFMT[0] = CSL_FMK(SPI_SPIFMT_CHARLEN, 8) |
CSL_FMK(SPI_SPIFMT_PRESCALE, 2) |
CSL_FMKT(SPI_SPIFMT_POLARITY, HIGH);
/* ... */
/* here SPI 1 is configured to use IRQ 4 (the highest priority) */
/* ... */
/* activate SPI */
CSL_FINST(gCommDev->SPIGCR1, SPI_SPIGCR1_ENABLE, ENABLE);
How is it possible for the SPI 1 Rx to stop triggering interrupts? Do all status flags have to be cleared and the Rx buffer be emptied (is the above code sufficient)? One thing I do not check is the "dropped interrupt" register in the interrupt controller. Could this help me recover?
Best regards,
SC