Other Parts Discussed in Thread: CC3200
Hello,
For our project we have implemented our own SPI driver (GSPI).The driver works as a slave and receives data from an external board using a clock speed of 20Mhz. The implementation uses the DMA in Ping-Pong mode, since we have other tasks running in the system and wanted to avoid unncessary overhead. The environment is FreeRTOS with the latest service pack and SDK.
The use-case that fails, involves a transfer of1440 bytes. The primary DMA channel is setup to transfer 1024 bytes and the alternate to transfer 416 bytes, then the peripheral is enabled. It is secured the master does not start sending before the setup is performed, the SPI peripheral is enabled and the DMA configured (the master starts sending only after CC3220s sets a pin to high).The start data is present in the buffers, also the primary DMA is always succeeding in transfering the data from the bus.
Sometimes, the alternate channel misses some bytes(1-400 bytes, varies from execution to execution).
If I enable the SPI overflow ISR then I can see the Interrupt is triggered in the cases when the alternate fails to perform the transfer. The SPI FIFO contains data in these cases.
The TX FIFO is disabled, the TX DMA is not used, we are only interested in reading data from the bus for this use-case.
If, before starting the transfer, I suspend all FreeRTOS tasks and busy-wait for the dma to finish, the transfer will succed almost always (fails ~1 in 20000). If I don't suspend the tasks, it fails 1 in 80 tries.
There are no other participants connected on the SPI bus, just the master and one slave (CC3220S). The DMA error ISR is not triggered. Checking the DMA registers 1 second after the transfer is started (the timeout we implemented for a transfer) or during the RX overflow ISR shows the following:
- the DMA channel is enabled (channel 6)
- UDMA_ATTR_ALTSELECT is set
- WAITSTAT register bit 6 is 0 : not waiting for a request <- does this mean the SPI is actually actively requesting that DMA performs the transfer ?
- UDMA_ATTR_REQMASK attribute is not present
- Mode is 0 (stopped) for the primary and 3 (PingPong) for the alternate
- Reading remaining bytes to transfer from the control table shows 159 (varies from transfer to transfer) bytes are still to be transfered.
- 4 bytes are remaining in the UART FIFO (checked by actually reading them until FIFO indicates empty)
The current theory we have is that some other task is running, accessing the AHB and taking priority from the DMA (manual states the DMA uses idle bus cycles and that the CPU always has priority). This leads to FIFO overflow and then loss of data. The dramatic improvement we get by suspending other tasks seems to support this. However the other tasks we have running perform no significant access to the AHB (taking 4 adc samples every 1 second, very small length UART prints). There is also the SL Task where it looks like some SPI polling transfers are performed that migh keep the AHB busy.
In order to adress this we have increased the DMA arbitration size to 8 words (word is 1 byte) and SPI RX FIFO trigger level to 8 also, so it matches. We have tried setting the UDMA_ATTR_HIGH_PRIORITY property to the DMA and also UDMA_ATTR_USEBURST. These have shown no significant improvement. We have also tried lowering the speed to 10Mhz, also no improvement.
Could you provide some insight on some points we might have missed ?
Is it actually feasible that the DMA loses arbitration to the CPU enough for the SPI RX FIFO to overflow ?