PSoC6 SPI Transfer with DMA with variable transfer length

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

cross mob
andrew-elsayeh
Employee
Employee
10 sign-ins 5 sign-ins First reply posted

Hello, I am trying to implement a non-blocking SPI Send function with DMA on the PSoC6 with ModusToolbox. The example code ("SCB SPI Master SPI") does almost that, but transfers 12 Bytes every time.

The data that I send is stored in a buffer that 32000 Byte Buffer, and sometimes I need to send the entire context of the buffer, and sometimes just parts of it (say 500-32000 Bytes). 

 

Right now, I use

cyhal_spi_transfer_async(&mSPI, tx_data, size, NULL, 0); 
 
This works pretty well, however I would like to improve the performance of my program by using DMA to save some CPU time, however I was not able to get it working, and have some questions. 
 
1- Can DMA handle such a large transfer (ex: 32000 Bytes) or would I need some special configuration to split up a large transfer into multiple ones? It seems that the PSoC3 and PSoC5 had a limit of 4096 Bytes per transfer, is that still the case for the PSoC6?
 
2- What drivers should I use for implementing this. Right now I am using the HAL for SPI, and I tried using cyhal_dma to put the data into mSPI.tx_buffer but that did nothing. Do I need to switch to the PDL for SPI and DMA?
 
3- Is there any example code/KB/AppNote that describes something similar so I can look into it? 
 
Thanks! 
0 Likes
1 Solution
Ekta_N
Moderator
Moderator
Moderator
750 replies posted First like given 250 solutions authored

Hello @andrew-elsayeh 

Here are the answers to your questions:

1.PSoC 6 supports transfer of up to 65536 data elements per descriptor with 8-bit, 16-bit, or 32-bit data widths at both source and destination.

2. Depending upon your choice it is possible to use both HAL or PDL for configuring the DMA. You can refer to the following pages which contains details regarding configuring DMA using PDL (https://cypresssemiconductorco.github.io/psoc6pdl/pdl_api_reference_manual/html/group__group__dma.ht... and HAL (https://cypresssemiconductorco.github.io/psoc6hal/html/group__group__hal__dma.html)

3. You can refer to the following Appnote : DMA on PSoC 6 that describes different DMA configurations and use cases, and explains how to design with DMA to achieve the most efficient and fastest data transfers.

Thanks and Regards

Ekta

View solution in original post

0 Likes
4 Replies
Ekta_N
Moderator
Moderator
Moderator
750 replies posted First like given 250 solutions authored

Hello @andrew-elsayeh 

Here are the answers to your questions:

1.PSoC 6 supports transfer of up to 65536 data elements per descriptor with 8-bit, 16-bit, or 32-bit data widths at both source and destination.

2. Depending upon your choice it is possible to use both HAL or PDL for configuring the DMA. You can refer to the following pages which contains details regarding configuring DMA using PDL (https://cypresssemiconductorco.github.io/psoc6pdl/pdl_api_reference_manual/html/group__group__dma.ht... and HAL (https://cypresssemiconductorco.github.io/psoc6hal/html/group__group__hal__dma.html)

3. You can refer to the following Appnote : DMA on PSoC 6 that describes different DMA configurations and use cases, and explains how to design with DMA to achieve the most efficient and fastest data transfers.

Thanks and Regards

Ekta

0 Likes

Hello @Ekta_N

Thank you for your help! I tried setting up the DMA using Hal to transfer the data into TX_FIFO_WR but I've encountered a couple of problems.

 

1- If I set the .length  property of the cyhal_dma_cgf_t  to any number greater than 256 the DMA Transfer never finishes (The DMA Transfer Done ISR is never executed)

2- Even if I limit my SPI transactions to a small value and try to send them, I don't seem to be getting any response from my SPI Slave. I currently don't have access to a logic analyzer, but I am suspecting that maybe just putting the data into the TX_FIFO_WR is not enough when SPI is setup using HAL. Am I write? Do I need to be calling another function myself to initiate the transfer such as manually pulling the SS line, or does the SPI Block take care of that automatically?

0 Likes

Hello @Ekta_N ,

I have made some progress on my project but am still encountering a bunch of problems. 

1- I changed my code to configure SPI using the device configurator and the pdl instead of the HAL. I then used the Cy_SCB_SPI_Transfer function instead of cyhal_spi_transfer_async. This didn't work because the SPI callback function only gets fired once when the transfer is started, but never again when the transfer is done, which causes my program to wait for the SPI transfer forever.

 

2- I then replaced Cy_SCB_SPI_Transfer with Cy_SCB_SPI_WriteArrayBlocking (and waited for the transfer to be done). Surprsingly, I got a huge performance increase compared to using cyhal_spi_transfer_async. The only explanation I can find for this is that because I configured SPI using the PDL, I can actually turn oversampling down to 2 and increase the frequency to 50Mhz, although I doubt that this is the only reason. The HAL does not allow this even if the MISO pin is not connected (the minimum oversampling in the settings is always 4). I believe this should be changed. 

3- I then stopped using the SPI send functions at all, and configured DMA to put the data from the buffer into the TX_FIFO. I did this using HAL. The problem with the length being limited to 256 is because when the burst size is set to 0, the HAL tries to setup a 1D transfer which is limited to 256 data elements.  I manually calculated the biggest factor of my data_length under 256 and configured the DMA channel everytime with a different length everytime I needed to transfer something. With a very small buffer (= slow program speed) the content of the buffer is indeed transfered but it seems that some of it gets distorted or messed up for some reason. The bigger the buffer (and faster the program) the more the data gets completely distorted. I have no idea what's causing this. 

0 Likes
Ekta_N
Moderator
Moderator
Moderator
750 replies posted First like given 250 solutions authored

Hello @andrew-elsayeh 

1. You will need to enable the transfer completer event and register  callback function that will be called when one of the events enabled by cyhal_spi_enable_event occurs. Through this you will come to know when the SPI transfer is complete. For more details on this function you can refer to the cyhal_spi_register_callback() and the cyhal_spi_enable_event() functions in the HAL documentation: https://cypresssemiconductorco.github.io/psoc6hal/html/group__group__hal__spi.html

2. Based on your observation I would recommend you to use PDL for both SPI Master and DMA. 

You can refer to the SCB_SPI_Master_DMA code example as a reference to configure the DMA and SPI Master.

You can use the DMA descriptor functions: https://cypresssemiconductorco.github.io/psoc6pdl/pdl_api_reference_manual/html/group__group__dma__d... to change the number of data elements to transfer during runtime.

3.  Can you attach a simple project so that I can reproduce the issue at my end? 

Thanks and Regards

Ekta

0 Likes