I'm having trouble with DMA transfers, specifically the "source wrap" functionality with burst transfer from the ADC channel data registers. Intended theory of operation is as follows:
Problem:
I never get any values transferred into the buffer by DMA. I set a breakpoint on ADC interrupt to watch the ADC registers and buffer variables. I can see the ADC Channel Data registers change, but the buffers remain empty.
However, if I change line 43 to "kDMA_NoWrap", everything runs as expected. On the first ADC Sequence complete interrupt, the expected values from the ADC Channel Data registers are transferred, subsequent transfers keep stepping through the memory which comes after the ADC Channel Data (because the "wrap" feature is not enabled).
What am I missing?
SDK 2.6.0
FSL_DMA_DRIVER_VERSION 2.3.0
Code snippet for DMA configuration:
Hello Matt Schrader,
1) So do you meaning when " if you change line 43 to "kDMA_NoWrap", your project can work well ?
If yes, I think you can do not use the DMA burst function.
2)If you still want to use DMA burst mode, please check the total transfer total length.
"The total transfer length as defined in the XFERCOUNT bits in the XFERCFG
register must be an even multiple of the burst size. Note that the total number
of bytes transferred is: (XFERCOUNT + 1) x data width (as defined by the
WIDTH field)."
Hi Alice_Yang,
1) When using "kDMA_NoWrap", the burst function works as I would expect. This means that the very first transfer uses the correct source addresses (ADC result registers), but the source address keeps incrementing on each transfer until the buffer is full. So the 2nd through the last transfers are data from incorrect source addresses (after the ADC result registers in memory). I can confirm that the data in my buffer is the expected result by using the debugger memory monitor. This confirms that other parameters about the DMA setup are working correctly, and my expectation is that changing to "kDMA_SrcWrap" would get the exact result I am going for. However, when I try to use the source burst wrap feature, the transfers never happen at all. The buffer remains empty.
From the manual:
Source Burst Wrap. When enabled, the source data address for the DMA is
“wrapped”, meaning that the source address range for each burst will be the
same. As an example, this could be used to read several sequential registers
from a peripheral for each DMA burst, reading the same registers again for
each burst.
2) I have made sure that this condition is satisfied. "ADC_DMA_BUFF_LENGTH" (as seen in lines 20 and 21) was kept small for testing (16) meaning the number of total transfers is 64.
I am currently pursuing some workarounds, but of course I would like to understand the root cause. Are there any examples of using burst mode to transfer multiple ADC channel results to a buffer?
Hello Matt,
Which chip do you used ? It seems there isn't multiple ADC channel +DMA burst demo, only one channel demo under SDK. Please send your project, I will help you check it on my side.
BR
Alice
Hi Alice,
Here is an example project which will run on the OM13092 (LPC54608 dev board). I started with the SDK example "lpcxpresso54608_lpc_adc_dma". I added a second ADC channel and I have attempted to use burst mode to transfer results from both channels into a single buffer with interleaved data.
See the DMA trigger struct setting (line 226):
dmaChannelTriggerStruct.wrap = kDMA_NoWrap;
Example will run with this setting and fill the buffer. The problem is the buffer will be filled with the values as follows:
ADC_CH0 result, sample 0
ADC_CH1 result, sample 0
ADC_CH2 result, sample 1
...
ADC_CH11 result, sample ?
...
random values from other memory until buffer full
When I change line 226 as follows:
dmaChannelTriggerStruct.wrap = kDMA_SrcWrap;
It the transfer does not happen. The buffer is all zeros. The desired functionality (expected result) is that the buffer is filled like this:
ADC_CH0 result, sample 0
ADC_CH1 result, sample 0
ADC_CH0 result, sample 1
ADC_CH1 result, sample 1
ADC_CH0 result, sample 2
ADC_CH1 result, sample 2
....
ADC_CH0 result, sample n
ADC_CH1 result, sample n
Am I misunderstanding the usage of the wrap setting?
Hello Matt,
- From your code I know you want to measure two ADC channels and save the datas to buffer using DMA.
So recommend you use the DMA Ping-Pong mode, you can refer to the below two threads:
LPC54114 DMA Linked Transfer Ping Pong - Circular Buffers
After I test the code and read UM, it seems only set the DMA transfer size to 2 (equal to channel number), then can used burst mode, it means in your code #define NUM_SAMPLES 1U. Because in RM page 1083:
"The burst size can be set to one in
the DMA channel control register. If the number of ADC channels is not equal to one of the
other DMA-supported burst sizes (applicable DMA burst sizes are 1, 4, 8), set the burst
size to one.The DMA transfer size determines when a DMA interrupt is generated. The transfer size
can be set to the number of ADC channels being converted. Non-contiguous channels
can be transferred by the DMA using the scatter/gather linked lists."
Anyway, I think the better way is use Ping-pong mode.
- BTW,If DMA is used for a sequence, the corresponding sequence interrupt must be disabled in the INTEN register.
Hope it helps,
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Using LPC54607J256ET180 on a custom PCB. I will try to pull together some sample code which illustrates the problem and runs on the OM13092 development board.