How can I reliably make variable sized writes using SPI via 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.
PaPr_1276616
Level 1
Level 1

Hi,

I'm trying to write data over SPI using DMA.  I have tried to implement methods used in the Cypress examples, but as soon as I add the feature of variable sized payloads using the API function DMA_SetNumDataElements() the resulting data stream is broken.

I have kept this project extremely simple, it is based on the PSoC Creator Example Project "PSoC 4 DMA SPI Example Project 1.0".

I am using the CY8CKIT-043 (4200M).  I removed the slave hardware, to further simplify the project.

I loaded the master Tx buffer as follows:  static const int8 masterTxBuffer[] = {"abcdefghijklmnopqrstuvwxyz1234567890"};

"I have (intended to, at least!) coded the master to alternate writing:

a two byte transfer  [ a, b ]  followed by a 32 byte transfer [ a, b, ... z, 1, 2, ... 6 ], and performing this sequence four times.

I use a Saleae Logic 8 to monitor the SPI master transmit.  See the output file attached.  The first transaction is over 40 bytes, which causes a wrap-around of the masterTxBuffer.   It does not loop properly, either.

I would *greatly* appreciate any help with making this simple DMA scheme run properly.

My project is attached,

Cheers,

Paul

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

Hi Hari,

I have found the answer, which I'll share here in full.  There seems to be a subtlety in the use of the DMA component when using the API function DMA_SetNumDataElements(). There is a requirement that no changes to the descriptor be made while it is 'validated'.  There is an API function to validate the descriptor, DMA_ValidateDescriptor(), but not one to invalidate it. The DMA component can be set to automatically invalidate when the transaction completes, using the configurator.

Now, the descriptor is automatically validated when the call to DMA_Start() occurs, which implies the DMA component will always use the user provided value for 'Number of data elements to transfer' from the relevant descriptor tab of the DMA configurator, for the first transaction.  After that transaction is completed, the firmware may call DMA_SetNumDataElements() and then revalidate the descriptor.

I *wrongly* assumed the configurator tabe would be loaded with a 'Number of data elements to transfer' value large enough to take any of the payload I generate.  This caused the first transaction to always be too long.

Other than that, I had a bug where I revalidated the descriptor before attempting to update the number of elements.  This was because I based my code on the Cypress example (PSoC 4 DMA SPI Example Project 1.0) which didn't alter transaction length.

Hari, thank you for all your time and input with this issue, please see my workign solution attached.

Regards,

Paul

View solution in original post

0 Likes
4 Replies