SD SPI Mode with DMA

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

cross mob
lock attach
Attachments are accessible only for community members.
jiwa_284501
Level 3
Level 3
First like received First like given Welcome!

Hello,

I have tested a project available on GitHub for PSoC5LP, it works fine. I use this component because the bitrate to transfer to SD Card is faster than emFile (Cypress Component)

GitHub - honet/PSOC5DMASDSPI: SPI mode SD-Card interface for PSoC5LP with DMA. (fatfs porting)

I want to adapt it on PSOC6, we are face to some difficulties. (compilation error)

In attached project we have recreate the component and import API and Library files.

I have performed some change on "api.c" file to by compatible with new PSoC6 capabilities, mainly on DMA purpose.

Based on original project for PSOC5LP, can you help us to adapt it for PSoC6?

Best Regards,

Jimmy.

0 Likes
1 Solution
MeenakshiR_71
Employee
Employee
100 likes received 50 likes received 25 likes received

Hello Jimmy,

Quick comments on the error you are facing -

1. The name you used for the "RX_DMA_IRQ_cfg" in api.c should be "`$INSTANCE_NAME`_RX_DMA_IRQ_cfg"

2. The header file required for the IRQ_cfg structure is "cyfitter_sysint_cfg.h" - so include it in api.c

3. Since the api.c file is generated and built for both CM0+ and CM4, the code expects the "cfg" structure for both the cores. However, when you select/map the interrupt in the "dwr" interrupts tab, by default they are mapped to CM4 ONLY. You can map the interrupt to both CM0+ and CM4 by enabling them in the dwr to overcome the error. However, we do not recommend such use. So in order to avoid that, you probably want to encapsulate the interrupt related code like below in the api.c

#ifdef `$INSTANCE_NAME`_RX_DMA_IRQ__INTC_CORTEXM0P_PRIORITY

//CM0+ interrupt code

#endif

#ifdef `$INSTANCE_NAME`_RX_DMA_IRQ__INTC_CORTEXM4_PRIORITY

//CM4 interrupt code

#endif

With the above, the errors should go away. Since the zip did not have sdCard.c/.h files, I was not able to build it successfully. One other thing, I did not see SPI initialization ('SPI_Start()) code in api.c. You only call enable in the start, which is not enough to get the SPI up and running.

Let me know if this helps or you have any questions.

Regards,

Meenakshi Sundaram R

View solution in original post

10 Replies
MeenakshiR_71
Employee
Employee
100 likes received 50 likes received 25 likes received

Hello Jimmy,

Quick comments on the error you are facing -

1. The name you used for the "RX_DMA_IRQ_cfg" in api.c should be "`$INSTANCE_NAME`_RX_DMA_IRQ_cfg"

2. The header file required for the IRQ_cfg structure is "cyfitter_sysint_cfg.h" - so include it in api.c

3. Since the api.c file is generated and built for both CM0+ and CM4, the code expects the "cfg" structure for both the cores. However, when you select/map the interrupt in the "dwr" interrupts tab, by default they are mapped to CM4 ONLY. You can map the interrupt to both CM0+ and CM4 by enabling them in the dwr to overcome the error. However, we do not recommend such use. So in order to avoid that, you probably want to encapsulate the interrupt related code like below in the api.c

#ifdef `$INSTANCE_NAME`_RX_DMA_IRQ__INTC_CORTEXM0P_PRIORITY

//CM0+ interrupt code

#endif

#ifdef `$INSTANCE_NAME`_RX_DMA_IRQ__INTC_CORTEXM4_PRIORITY

//CM4 interrupt code

#endif

With the above, the errors should go away. Since the zip did not have sdCard.c/.h files, I was not able to build it successfully. One other thing, I did not see SPI initialization ('SPI_Start()) code in api.c. You only call enable in the start, which is not enough to get the SPI up and running.

Let me know if this helps or you have any questions.

Regards,

Meenakshi Sundaram R

lock attach
Attachments are accessible only for community members.

Hello,

Thank's for your reply, it was very useful. Now me project build without error.

But for the moment, writing in SD doesn't works. This part need to be debugged again.

Please find attached me project which include your corrections.

Best Regards

Jimmy.

0 Likes
lock attach
Attachments are accessible only for community members.

Hello,

Debug of SPI communication on this project is good now, all signals between PSoC6 and SD Card seems to be as expected. (chip select/MISO/MOSI/SCLK)

My main issue is to set the 2 DMA for source and destination pointers addresses for SPI_TX FIFO and SPI_RX_FIFO.

On SPI PSoC5LP version i use "rx_interrupt" and "tx_interrupt" output pins, and 2 pointers registers was generated to have access to SPI RX en TX buffers. ("SDSPI_SPIMaster_TXDATA_PTR" and "SDSPI_SPIMaster_RXDATA_PTR").

On PSoC6 version, i use "rx_dma" and" tx_dma" outputs, theses 2 signals are good for me, same behavior of "rx_interrupt" and "tx_interrupt" on PSoC5 version.

But for DMA settings:

Cy_DMA_Descriptor_SetDstAddress(&`$INSTANCE_NAME`_TX_Descriptor_1, bufferTx);

Cy_DMA_Descriptor_SetSrcAddress(&`$INSTANCE_NAME`_RX_Descriptor_1, bufferRx);

What is the pointer for bufferTx and bufferRx of SPIMaster FIFO? I don't find any register or example on this topic.

This function can be useful? (When i use it, rx_dma and tx_dma trigger don't work).

`$INSTANCE_NAME`_SPIMaster_Transfer(bufferTx, bufferRx, BUFFER_SIZE);

My last version of my project:

Best Regards,

Jim.

0 Likes

Hello Jimmy,

Sorry for missing this thread - I was on a bit of travel past few days and missed to respond. Since, I don't have access to the setup you are using, I could not comment much on the hardware working either. Good to hear that you were able to debug further

Now, to your question: You can access the SPI TX FIFO using this - "&`$INSTANCE_NAME`_SPIMaster_HW->TX_FIFO_WR" and RX FIFO using "&`$INSTANCE_NAME`_SPIMaster_HW->RX_FIFO_RD". This should let you configure your DMAs properly.

Let me know if this resolves the issue. If not, I will try to see if I can setup the hardware somehow to provide additional support.

One other thing, I would recommend you to try testing the project without DMA (using the transfer APIs) and then enabling DMA. This eliminates multiple convoluted failure scenarios .

Regards,

Meenakshi Sundaram R

lock attach
Attachments are accessible only for community members.

Hello,

We have separate this SD project of our main project to have a simple PSoC project and hardware setup. I hope this project can be re-used by another Cypress Community developer. I think this is a very interesting topic because for example on PSoC5LP we can save data in SDCard file with a datarate of 800kB/s with SPI communication protocol, with EmFile we have 80KB/s. This is not enough for our futur project application.

To return to the subject, now DMA FIFO pointers should be ok, thank you.

The project doesn't work again but i need more time to debug.

For the moment:

"f_open" in main function is blocking...

"disk_initialize" and "f_mount" seems to be ok in sdCard.c file (Debug Mode execution)

Probably an issue in "SDSPI_SetDMAMode" function.

I have tested without DMA, and it work fine.

Please find attached my project and a picture we show my hardware setup, i have missing the oscilloscope in diagram.

Best regards,

Jimmy.

Let me try this out sometime this weekend and get back.

0 Likes

Hello!

I think the issue comes from this follow instruction (in "SDSPI_api.c" line 147), it's a blocking loop because in my case nTransferFlag always at '1'.

// wait for transfer

while(nTransferFlags & TRANSFER_WAIT_RXDMAISR);

I think my problem is due to the previous instruction (not implemented in PSOC6 code version...)

CyDmaChSetRequest(TXDMA_Channel, CPU_REQ);  //trigger transfer (for PSOC5LP)

What is the equivalent function for PSOC6?

Jimmy.

0 Likes

Jimmy,

To trigger a DMA channel request from software you can use the below API -

Cy_TrigMux_SwTrigger(TRIG0_OUT_CPUSS_DW0_TR_IN0, 1); // Triggers DW0's Channel 0 and the trigger lasts 1 cycle)

If you dont know the channel or DW block that will be allocated by fitter, you can use the below equation to arrive at the first parameter -

dwChannelTrigOut = 0x40000000 | (<DMA_NAME>_DW_BLOCK << 😎 | (<DMA_NAME>_DW_CHANNEL);

Cy_TrigMux_SwTrigger(dwChannelTrigOut, 1);

Let me know if this helps.

Regards,

Meenakshi Sundaram R

0 Likes
lock attach
Attachments are accessible only for community members.

Hi msur,

I implemented last week this code to trigger DMA channel, unfortunately today i don't know how i can debug more my code to find why DMA does'nt works.

I need your help to debug my project.

There is 2 attached archive:

-SdSPI_PSOC6 => my current project.

-Component_PSOC5_Version => contain the DMA_SPI component which works fine on PSOC5LP. (to compare API and SPI topdesign settings)

My adaptation on PSOC6 is probably bad, but where...

Thank in advance,

Jimmy.

0 Likes

Hi all,

There are some DMA functions without equivalent between PSOC5 and PSOC6, here a merge view, i try to "translate" PSOC5 code on PSOC6 but i think this is not enough.

SDCard_PSoC5vsPSoC6.PNG

For me

RXDMA_Channel = `$INSTANCE_NAME`_RX_DmaInitialize(...)

TXDMA_Channel = `$INSTANCE_NAME`_TX_DmaInitialize(...)

TXDMA_TD[0] = CyDmaTdAllocate();

RXDMA_TD[0] = CyDmaTdAllocate();

are perform by DMA Component Settings Panel.

But for:

CyDmaTdFree(TXDMA_TD[0]);

`$INSTANCE_NAME`_RX_DmaRelease();

Can you give me the equivalents functions?

another function, in psoc5 code version there is:

// stop DMA.

CyDmaChSetRequest(TXDMA_Channel, CPU_TERM_CHAIN);

What is the PSOC6 equivalent function please?

Cy_DMA_Disable(`$INSTANCE_NAME`_TX_DW__BLOCK_HW); is enough?

Thank's in advance!

Jimmy.

0 Likes