SPI DMA question.

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
EdHa_4455331
Level 5
Level 5
25 replies posted 25 sign-ins 10 replies posted

To work around my issues with Cy_SCB_SPI_Transfer()  not working for large blocks of data at 4x oversampling, I am going to implement a DMA route for those exchanges.

I understand the overall DMA scheme of things: you set up a DMA transfer from a source buffer to the SPI's Tx fifo. But... Let's say I'm sending a block of 1000 data bytes, but the SPI Tx fifo is only 128 bytes long. What keeps the DMA transfer from overrunning the Tx fifo?

Thanks,

Ed H.

0 Likes
1 Solution
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi EdHa_4455331

The first half is correct. The SPI block only really takes care of the transmission of the elements in the Tx FIFO. What needs to be transmitted is taken care either by the CPU or the DMA.

Cy_SCB_SPI_Transfer() works in conjunction with  Cy_SCB_SPI_SetActiveSlaveSelect(). Cy_SCB_SPI_SetActiveSlaveSelect just sets an internal value as to which slave to use, but Cy_SCB_SPI_Transfer() actually does the asserting/reseting of the slave enable system. OTOH, the dma channel has no concept of slave selection. So the DMA code will have to implement the low level details of enabling and disabling a particular slave.

Here too, the first statement is correct. It is the SCB block that takes care of asserting/deasserting the physical SS pin. But which pin to be used as SS is decided by writing the Cy_SCB_SPI_SetActiveSlaveSelect API.

A DMA only takes care of writing into/reading from the SCB FIFO. All other configurations such as choosing the SS pin, enabling the block etc must be done by the CPU in the main code. Once the active SS pin is selected by the CPU core, simply writing into the FIFO of the SCB will result in correct transmission of the packet.

Best regards,

Hari

View solution in original post

4 Replies
VenkataD_41
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi Ed,

The DMA in PSoC 6 supports 2D transfer of data from source to destination.

In your case you can configure your source as 2D array with 128 bytes in each row. The destination is a single 128 byte array (SPI TX FIFO)

What keeps the DMA transfer from overrunning the Tx fifo?

You can set the Trigger input type as One X loop per transfer. Here X loop will be the 128 byte array.

So, you need to Trigger the DMA (either through Hardware or Firmware) after you knew that the SPI TX FIFO is empty.

Please refer PSoC Creator code CE221120 PSoC 6 SPI Master which has a project to work with SPI using DMA.

https://www.cypress.com/documentation/code-examples/ce221120-psoc-6-mcu-spi-master

Also please refer an application note on PSoC 6 DMA for more information on DMA.

https://www.cypress.com/documentation/application-notes/an228753-dma-psoc-6-mcu

Hope this helps !

Thanks

Ganesh

Hi EdHa_4455331

You usually trigger the Channel of DMA using the TX Trigger output signal from the SPI (SCB) block. This signal's behavior is controlled by the TX FIFO level setting. You should set TX FIFO level to a number (0 - 127) less than the maximum FIFO depth (128). If you set this TX FIFO level to say 64, the TX Trigger output signal will be active until the TX FIFO has 64 elements. Above that the TX FIFO level, the TX Trigger output signal is de-asserted. Therefore giving no further trigger to the DMA channel. This ensures that the TX FIFO is not overrun.

You need to configure the DMA Channel to transfer one element per trigger and the number of elements to be transferred can be decided using the X loop and Y loop settings.

In your use case, if you have to transfer 1000 bytes, you do the following;

1. Set TX FIFO level to 64 (or anything between 1 to 127)

2. DMA settings can be something like below. You will transfer 250 x 4 bytes = 1000 bytes.

pastedImage_2.png

Regards,

Bragadeesh

Regards,
Bragadeesh
0 Likes

That helped a lot, but I am still trying to develop a correct mental model.

Please let me know if any of the following is incorrect:

When using the DMA method, the SPI block is really just a passive agent. It really doesn't know when any given SPI exchange has ended. Its only real role it to check on the levels in the tx fifo and rx fifo levels and generate triggers for the DMA block based on those levels. So the SPI block only needs to be initialized and enabled.

Cy_SCB_SPI_Transfer() works in conjunction with  Cy_SCB_SPI_SetActiveSlaveSelect(). Cy_SCB_SPI_SetActiveSlaveSelect just sets an internal value as to which slave to use, but Cy_SCB_SPI_Transfer() actually does the asserting/reseting of the slave enable system. OTOH, the dma channel has no concept of slave selection. So the DMA code will have to implement the low level details of enabling and disabling a particular slave.

Right so far?

Thanks,

Ed H.

Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi EdHa_4455331

The first half is correct. The SPI block only really takes care of the transmission of the elements in the Tx FIFO. What needs to be transmitted is taken care either by the CPU or the DMA.

Cy_SCB_SPI_Transfer() works in conjunction with  Cy_SCB_SPI_SetActiveSlaveSelect(). Cy_SCB_SPI_SetActiveSlaveSelect just sets an internal value as to which slave to use, but Cy_SCB_SPI_Transfer() actually does the asserting/reseting of the slave enable system. OTOH, the dma channel has no concept of slave selection. So the DMA code will have to implement the low level details of enabling and disabling a particular slave.

Here too, the first statement is correct. It is the SCB block that takes care of asserting/deasserting the physical SS pin. But which pin to be used as SS is decided by writing the Cy_SCB_SPI_SetActiveSlaveSelect API.

A DMA only takes care of writing into/reading from the SCB FIFO. All other configurations such as choosing the SS pin, enabling the block etc must be done by the CPU in the main code. Once the active SS pin is selected by the CPU core, simply writing into the FIFO of the SCB will result in correct transmission of the packet.

Best regards,

Hari