Looking for a timer-driven ADC example with DMA for the LPC55S69

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Looking for a timer-driven ADC example with DMA for the LPC55S69

391 Views
scottm
Senior Contributor II

I'm looking for an example that demonstrates the proper way to set up a timer-driven ADC conversion with DMA for storing samples.

All of the provided examples only use software triggers. I'm not sure what the DMA example is trying to accomplish - it says it uses "ping-pong" mode to store results, but the two transfer descriptors are set up identically and save a single value to the same location. It's an example of transfer chaining but not ping-pong buffering.

In table 753, it looks like CTIMERs are mistakenly called "State Counter Timers". Hardware trigger 11 is listed as "ARM tx event" but that's not defined anywhere that I can find. What is this interrupt? All Google results for "ARM_TXEV" come back to NXP docs and it's never described, as far as I can tell.

Obviously I can set up a CTIMER to periodically trigger the ADC channel and have the ADC trigger the DMA. I'm hoping for a working example in case there's more to the ADC command sequencing. I've spent enough time debugging the Kinetis PDB/ADC/DMA relationship that I'd rather not repeat the same learning curve for the LPC equivalent.

Also, where can I find complete docs on the MCUX DMA driver? The ADC DMA makes two calls to DMA_SetupDescriptor(), which has no documentation beyond "Note: This function do not support configure wrap descriptor" which isn't even a valid English sentence and says nothing about what it does.

The first call to DMA_SetupDescriptor() duplicates all of the information in the call to DMA_PrepareChannelTransfer() above. There's no explanation as to how the setup sequence works or why this duplication is needed. And since it appears to set up a useless function - namely using two transfer descriptors to do the work of one, with the same source and destination - it's hard to deduce why the example does what it does.

It seems like the most likely explanation is that someone was given the assignment of creating a demo that used two DMA transfers in ping-pong configuration to read and store ADC results, and they did that in a way that met the literal requirements without actually doing it in a way that reflects real-world usage. I don't know anyone who would set up DMA to return results from a single, manually-triggered conversion - let alone use TWO descriptors to do the same thing. I think you call this attitude "差不多"? It's extremely frustrating.

Edit: On closer inspection, it gets even worse. It appears that the DMA hardware trigger isn't even used - the demo simply polls the FIFO status to wait until results are ready and then manually launches the DMA transfer.

Thanks,

Scott

2 Replies

340 Views
scottm
Senior Contributor II

The error I'm referring to is here:

scottm_0-1684171552305.png

There is no "State Counter Timer". The SCT is the State Configurable Timer. The manual describes CTIMERs as "standard counter/timers" - they don't have "state" anywhere in the name.

I was able to get my CTIMER+ADC+DMA setup working over the weekend. Doing it with the MCUX driver is frustrating because of the lack of documentation.

From what I've seen, it looks like some of the functions implement a configuration wrapper ("configure wrap descriptor") and have storage for a descriptor or two, but some of the functions bypass those and allow lower level configuration. There's no explanation about any of that and the examples are inconsistent in their usage.

The example you sent me, and the code I ended up with on Saturday, use DMA_PrepareChannelTransfer(), DMA_SubmitChannelTransfer(), and then DMA_SetupDescriptor(). The channel chain demo uses DMA_SetChannelConfig(), DMA_SetupDescriptor(), and DMA_SubmitChannelTransferParameter(). The interleave transfer demo uses DMA_SetupDescriptor() and DMA_SubmitChannelDescriptor(). None of them provide any explanation of why they use the calls they do. The "Typical use case" section only says to see the demos. The demos provide no useful comments. I'm still not sure why DMA_PrepareChannelTransfer() is needed in my code and why I can't use DMA_SubmitChannelDescriptor() like the interleave demo but I haven't had time to look more closely.

In some cases just blindly copying the demo code might be acceptable, but it's not so useful when you have to build a real-world product and have more than one thing using DMA. You need to know what each function call does and how it relates to the hardware documentation. The only way I can see to do that now is to reverse-engineer the driver code.

Here's what I came up with on Saturday:

scottm_1-1684173101701.png

To make it a useful ping-pong buffer, the two descriptors point to different adc_rx_buf buffers and they alternate between IntA and IntB so the callback can distinguish which buffer was just filled. This is a useful feature that I don't think the Kinetis eDMA has, but there is zero documentation for the DMA callback in MCUX - you have to look at the source to see what events generate callbacks and how they're passed.

Another place the examples fall short is in the destination address increment setup. The example you provided and the one I referenced before both write to a single destination variable with no increment. The relevant parameter is interchangeably described as "interleave" and "increment", which to me suggest different things - interleaving (as illustrated by the interleaved transfer demo) means skipping ahead so that another transfer can write data into the spaces between. So with an interleave of 0 I would expect a normal increment with no extra spaces, and an interleave of 1 would leave one word of space between each word. The parameter is just an increment, though.

It looks like maybe this wasn't always the case. DMA_PrepareTransfer() sets the source and destination increment based on the type, e.g. kDMA_PeripheralToMemory. Again, nothing is documented.

Scott

 

 

0 Kudos

350 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

As the following Table 753 in UM11126.pdf ver2.4, the SCT(state configuration timer) is not CTimer, the SCT is an independent module which can generate complex PWM signal, of course, it can generate ADC triggering signal with constant cycle.

For detailed inf, pls refer to chapter Chapter 24: LPC55S6x/LPC55S2x/LPC552x SCTimer/PWM(SCT) in UM11126.pdf

Regarding the "ARM_TXEV", there is an instruction "SEV" for Cortex-M33, which can generate event to the processor.

xiangjun_rong_0-1684114367689.png

For the CTimer hardware ADC triggering and DMA example, pls refer to the attached project, if you have any issue, pls update the ticket, I will have a try on my side.

Hope it can help you

BR

XiangJun Rong

 

0 Kudos