DMA from SPIS round robbin

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

cross mob
Anonymous
Not applicable

I'm trying to read the SPIS with DMA.  I have the following setup

/* Defines for DMA_5 */

#define DMA_5_BYTES_PER_BURST 1

#define DMA_5_REQUEST_PER_BURST 1

#define DMA_5_SRC_BASE (CYDEV_PERIPH_BASE)

#define DMA_5_DST_BASE (CYDEV_SRAM_BASE)

uint8 DMA_5_Chan;

uint8 DMA_5_TD[2];

uint8 spisbuffer0[16];

uint8 spisbuffer1[16];

void startDMA5()

{

/* DMA Configuration for DMA_5 */
DMA_5_Chan = DMA_5_DmaInitialize(DMA_5_BYTES_PER_BURST, DMA_5_REQUEST_PER_BURST,
    HI16(DMA_5_SRC_BASE), HI16(DMA_5_DST_BASE));
DMA_5_TD[0] = CyDmaTdAllocate();
DMA_5_TD[1] = CyDmaTdAllocate();
CyDmaTdSetConfiguration(DMA_5_TD[0], 16, DMA_5_TD[1], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
CyDmaTdSetConfiguration(DMA_5_TD[1], 16, DMA_5_TD[0], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
CyDmaTdSetAddress(DMA_5_TD[0], LO16((uint32)SPIS_1_RXDATA_PTR), LO16((uint32)spisbuffer0));
CyDmaTdSetAddress(DMA_5_TD[1], LO16((uint32)SPIS_1_RXDATA_PTR), LO16((uint32)spisbuffer1));
CyDmaChSetInitialTd(DMA_5_Chan, DMA_5_TD[0]);
CyDmaChEnable(DMA_5_Chan, 1);

}

The SPIS is set to interrupt on FIFO not empty.  That feeds to the DMA to trigger transfers.  The DMA is set for rising edge.  The DMA signal looks clean on my scope, with one pulse per byte on the SPI.  My SPI input clock is roughly 4 Mhz.

It works fine as it is reading the fist buffer.  It seems like when it starts filling the second buffer, instead,it fills both buffers with a constant, in this case, one of the bytes from my incoming data.  I used the DMA Wizard to set up these values.

Can I get some help understanding the proper way to set up round robbin reads of hardware?

0 Likes
1 Solution
NoriTan
Employee
Employee
25 sign-ins 5 questions asked 10 sign-ins

You set the TD_AUTO_EXEC_NEXT bit for the 1st and 2nd TDs.  This bit is used to trigger the next TD automatically. Following is the description in the DMA datasheet.

GS003338.png

When 1st byte is received from the SPI master, the 1st TD reads the received value and writes it to the buffer.  After that the 2nd TD will be executed without waiting for receiving the 2nd byte.  So, the SPI's DATA register is read and stored into the buffer.

If you want to execute one DMA transfer for an SPI byte, the flag should not be set for both TDs.

Regards,

Noriaki

View solution in original post

0 Likes
3 Replies
NoriTan
Employee
Employee
25 sign-ins 5 questions asked 10 sign-ins

You set the TD_AUTO_EXEC_NEXT bit for the 1st and 2nd TDs.  This bit is used to trigger the next TD automatically. Following is the description in the DMA datasheet.

GS003338.png

When 1st byte is received from the SPI master, the 1st TD reads the received value and writes it to the buffer.  After that the 2nd TD will be executed without waiting for receiving the 2nd byte.  So, the SPI's DATA register is read and stored into the buffer.

If you want to execute one DMA transfer for an SPI byte, the flag should not be set for both TDs.

Regards,

Noriaki

0 Likes
Anonymous
Not applicable

Thanks for the help.  I am almost there.

So if I want it to fill one buffer, then the next buffer, then return to the first buffer, continuously, which TD should the flag be set for? 

Is it possible for it to refill a single buffer over and over forever without restarting the DMA request?

What I'm trying to do here is have a really large FIFO buffer that I can read separately.  I am using a counter on the IRQ line to count how many bytes have been received.

0 Likes
Anonymous
Not applicable

It looks like it works correctly if I remove the NEXT flag from both TDs

0 Likes