- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello All,
I am trying to establish a Ping pong DMA to transfer data alternatively from two buffers. Buffer Size is 1000k(1MB). Can anyone give me any idea to perform this task?
Thanks.
Solved! Go to Solution.
- Labels:
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
AdityaK, Bob is right that the maximum transfer is 4095 bytes from a single TD but you can have multiple TDs to transfer the total length you need. What is the source of your data buffers -- a filter? ADC? Is your input array the same size as your output array? I have used pointers in each TD to reference a specific offset into the source or destination buffer. Be sure to reinitialize these pointers for each burst. For example:
uint16 *pA[4]; // Array of pointers to segments of data array from Filter A
void set_pointers() // Sets the pointers to the output arrays
{
uint16 j;
for (j = 0; j < SEGMENTS; j++) // and if SEGMENTS is #defined as 4 ...
{
pA
}
}
Then each TD uses one of the pA pointers. See them used in the last four lines in this code:
The following might be the reverse direction of what you are doing but it can be modified for your need.
/* DMA Configuration for dma_out_A */
/* Create a TD[5] that ENDs to avoid memory corruptions if the main loop is too slow to stop it */
dma_out_A_Chan = dma_out_A_DmaInitialize(dma_out_A_BYTES_PER_BURST, dma_out_A_REQUEST_PER_BURST,
HI16(dma_out_A_SRC_BASE), HI16(dma_out_A_DST_BASE));
dma_out_A_TD[0] = CyDmaTdAllocate();
dma_out_A_TD[1] = CyDmaTdAllocate();
dma_out_A_TD[2] = CyDmaTdAllocate();
dma_out_A_TD[3] = CyDmaTdAllocate();
dma_out_A_TD[4] = CyDmaTdAllocate();
CyDmaTdSetConfiguration(dma_out_A_TD[0], 2*LENGTH, dma_out_A_TD[1], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
CyDmaTdSetConfiguration(dma_out_A_TD[1], 2*LENGTH, dma_out_A_TD[2], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
CyDmaTdSetConfiguration(dma_out_A_TD[2], 2*LENGTH, dma_out_A_TD[3], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
CyDmaTdSetConfiguration(dma_out_A_TD[3], 2*LENGTH, dma_out_A_TD[4], dma_out_A__TD_TERMOUT_EN | TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
CyDmaTdSetConfiguration(dma_out_A_TD[4], 32, dma_out_A_TD[0], TD_AUTO_EXEC_NEXT);
CyDmaTdSetAddress(dma_out_A_TD[0], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[0]));
CyDmaTdSetAddress(dma_out_A_TD[1], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[1]));
CyDmaTdSetAddress(dma_out_A_TD[2], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[2]));
CyDmaTdSetAddress(dma_out_A_TD[3], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[3]));
CyDmaTdSetAddress(dma_out_A_TD[4], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)overflow_A));
CyDmaChSetInitialTd(dma_out_A_Chan, dma_out_A_TD[0]);
CyDmaChEnable(dma_out_A_Chan, 1)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think I have red that the maximum amount to transfer with a single TD is limited to 4095 bytes. Have a look into this appnote
Deeper information you will find here.
Happy coding
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Out of curiosity: do you have a secret PSoC device with 1MB RAM? Or do you use external memory?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Some ref material -
http://www.cypress.com/?rID=37793 AN52705 Getting Started with DMA
http://www.cypress.com/?rID=82680 AN84810 PSoC® 3 and PSoC 5LP Advanced DMA Topics
http://www.cypress.com/?rID=44335 AN61102 PSoC® 3 and PSoC 5LP - ADC Data Buffering Using DMA
http://video.cypress.com/video-library/search/dma/ Videos on DMA
https://www.youtube.com/results?search_query=dma+psoc Videos on DMA (some overlap)
Regards, Dana.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Dana
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You are always welcome!
Dana.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
AdityaK, Bob is right that the maximum transfer is 4095 bytes from a single TD but you can have multiple TDs to transfer the total length you need. What is the source of your data buffers -- a filter? ADC? Is your input array the same size as your output array? I have used pointers in each TD to reference a specific offset into the source or destination buffer. Be sure to reinitialize these pointers for each burst. For example:
uint16 *pA[4]; // Array of pointers to segments of data array from Filter A
void set_pointers() // Sets the pointers to the output arrays
{
uint16 j;
for (j = 0; j < SEGMENTS; j++) // and if SEGMENTS is #defined as 4 ...
{
pA
}
}
Then each TD uses one of the pA pointers. See them used in the last four lines in this code:
The following might be the reverse direction of what you are doing but it can be modified for your need.
/* DMA Configuration for dma_out_A */
/* Create a TD[5] that ENDs to avoid memory corruptions if the main loop is too slow to stop it */
dma_out_A_Chan = dma_out_A_DmaInitialize(dma_out_A_BYTES_PER_BURST, dma_out_A_REQUEST_PER_BURST,
HI16(dma_out_A_SRC_BASE), HI16(dma_out_A_DST_BASE));
dma_out_A_TD[0] = CyDmaTdAllocate();
dma_out_A_TD[1] = CyDmaTdAllocate();
dma_out_A_TD[2] = CyDmaTdAllocate();
dma_out_A_TD[3] = CyDmaTdAllocate();
dma_out_A_TD[4] = CyDmaTdAllocate();
CyDmaTdSetConfiguration(dma_out_A_TD[0], 2*LENGTH, dma_out_A_TD[1], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
CyDmaTdSetConfiguration(dma_out_A_TD[1], 2*LENGTH, dma_out_A_TD[2], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
CyDmaTdSetConfiguration(dma_out_A_TD[2], 2*LENGTH, dma_out_A_TD[3], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
CyDmaTdSetConfiguration(dma_out_A_TD[3], 2*LENGTH, dma_out_A_TD[4], dma_out_A__TD_TERMOUT_EN | TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
CyDmaTdSetConfiguration(dma_out_A_TD[4], 32, dma_out_A_TD[0], TD_AUTO_EXEC_NEXT);
CyDmaTdSetAddress(dma_out_A_TD[0], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[0]));
CyDmaTdSetAddress(dma_out_A_TD[1], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[1]));
CyDmaTdSetAddress(dma_out_A_TD[2], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[2]));
CyDmaTdSetAddress(dma_out_A_TD[3], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)pA[3]));
CyDmaTdSetAddress(dma_out_A_TD[4], LO16((uint32)Filter_HOLDA_PTR), LO16((uint32)overflow_A));
CyDmaChSetInitialTd(dma_out_A_Chan, dma_out_A_TD[0]);
CyDmaChEnable(dma_out_A_Chan, 1)