SCB_SpiUartReadRxData(void) fails in ISR context. | Cypress Semiconductor
SCB_SpiUartReadRxData(void) fails in ISR context.
Hi, Ive been assigned to work on a device utilizing the PSoC 4 as it's main processor. Unfortunately I have had no end of troubles when attempting to use the dedicated SCB blocks to implement a SPI control driver for an MCP2510 CAN controller.
It seems like many of the other peripherals the SCB blocks are designed for bulk data transfer. Normally this wouldn't be an issue except that the MCP2510 requires sequences of commands that require specific transitions on the slave-select line. Because the SCB blocks have auto-slave-select I would usually assign a GPIO pin to that function and use software control, but the inclusion of a mandatory transmit FIFO has made that impossible.
Because of this I have implemented a large state machine within the SCB ISR that triggers on the SPI done event. This allows me to generate each of the necessary setup/cleanup commands required before/after a CAN transaction.
Although I have the physical SPI communications operating correctly, (verified with a logic analyzer) I am completely unable to read from the RX FIFO while in the SCB interrupt. I am using the built-in software buffer (15 bytes) and have included my state machine code within the internal interrupt via the SCB_SetCustomInterruptHandler() function. For some reason whenever the SCB_SpiUartReadRxData() function is called within the ISR it unconditionally returns 0x00 regardless that the SCB_SpiUartGetRxBufferSize() function is correctly returning the number of bytes in the FIFO. Additionally after each faulty call to read from the FIFO, the number of available data bytes decreases properly.
I realize that the code that manages the internal buffers executes after my state machine code. However even when purposefully re-triggering the ISR after a receive in order to delay an ISR cycle, the SCB_SpiUartReadRxData() function still returns zeros. I have verified that the SCB_SpiUartReadRxData() function works properly outside of the interrupt, but unfortunately I can't easily move this sequence of reads outside the ISR since I need to immediately send cleanup commands (will overwrite data in FIFO) in order to release the interrupt system of the MCP2510. (Otherwise the CAN bus will error due to an overfull mailbox if another packet comes before the PSoC can get to sending the cleanup commands.)
I have been running the code through a debugger and it would seem that the internal FIFO isn't being populated (memory watch) even though the SPI done interrupt has fired and the SCB_SpiUartGetRxBufferSize() function claims there is data.
Before anyone asks, I can't use any UDB-based SPI devices since the UDB blocks are already utilized. I also can't upload my PSoC creator project as it contains proprietary code that I don't have the rights to distribute. If it is required I can write a similar file demonstrating how I have set up the state machine, but I would rather not take the time unless necessary.