2025-01-22 12:34 AM - edited 2025-01-22 02:36 AM
Hello, as the title goes: is it at all possible to enable both DMA and an analog window watchdog (AWD1) simultaneously on the ADC4?
What I'm trying to achieve is the following:
I managed to make the first 2 points work and I'm pretty happy with the results: I get an average current of ~ 7 µA (SMPS enabled) in Stop2, with ADC4 sampling at 500 Hz autonomously (triggered by LPTIM1/CH1) and AWD1 working as expected. So that's pretty good.
I then tried to implement a DMA transfer concurrently on the same ADC4 channel using LPDMA1, and this is where things go wild. DMA transfers and AWD1 on ADC4 don't seem to play well together. I haven't read anything particular about it in the reference manual or in the errata, but I may have missed it.
First issue when doing this is that the DMA seems to get only 1 request every 2 ADC conversions.
Second issue, that seems only related to enabling DMA transfers in ADC4, regardless of whether I enable a DMA channel or not. When setting the transfer mode with:
LL_ADC_REG_SetDMATransfer(ADC4, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
I get a very odd behavior of the MCU that seems related to the debug IP. Let me elaborate:
I haven't read anything related to that in the errata, but maybe I missed it.
Thanks for any pointers about these 2 issues!
Edit: I just want to add to this that it's the "unlimited" DMA mode (circular mode in the RM) that triggers this very odd behavior. In the "limited" DMA mode, it works as expected. Although, the downside is that it automatically stops the ADC when the transfer is done, so that the ADC needs to be restarted after that. But the circular mode behaves very erratically. If anyone's got any idea why...
Solved! Go to Solution.
2025-01-24 01:43 AM - edited 2025-01-24 01:45 AM
Hello, I worked on this some more and finally found out the culprit. So, here are my findings, if it can help anyone. The LPBAM is not trivial on this MCU range and there were no example available of what I was trying to achieve, especially when using LL.
To sum up:
To work around this, I changed my approach:
Finally, while implementing this approach, I ran into another issue that I also finally figured out:
The autonomous clock for SRAM4 is enabled like so:
LL_SRDAMR_GRP1_EnableAutonomousClock(LL_SRDAMR_GRP1_PERIPH_SRAM4);
So there you go. Hope it can help anyone who would run into similar "issues". I'm going to mark this post as "solution", as the issue is fixed and this post explains how.
2025-01-23 02:53 AM - edited 2025-01-23 03:12 AM
I managed to do some more testing with this. The AWD works fine along with the DMA. But. I was able to reproduce the odd behavior described above also in the "limited" DMA mode (DMA one-shot mode, DMACFG = 0).
In DMA one-shot mode, once the DMA transfer is complete, ADC conversions are stopped. This is described, although IMO not clearly at all in the corresponding paragraph in the RM, which states that "The scan sequence is stopped and reset" - what exactly does that mean? Conversions in that case are effectively stopped. But, if one restarts them by setting the CR_ADSTART bit (calling LL_ADC_REG_StartConversion(ADC4)), it does restart conversions, but the ADC gets into this odd state which makes the Debug IP go bonkers and then, the consumption when getting in Stop2 is ~ 40 µA instead of ~ 7 µA. I don't know what's up with that.
Maybe setting the CR_ADSTART bit when a DMA one-shot transfer is complete is not the right thing to do? The register documentation for this bit doesn't mention anything in the particular case of DMA one-shot transfers completed, which DOES stop conversions.
How are we supposed to restart conversions when that happens, if setting the CR_ADSTART is not the right thing to do?
To add to what I tested, if we keep ADC4 in a DMA transfer mode (LIMITED or UNLIMITED) after one successful complete DMA transfer and we restart conversions, this is what causes the odd power consumption afterwards. If we switch the DMA transfer mode to NONE after one first successful DMA transfer, and then restart conversions, it works normally (but obviously with no more DMA). Unless I missed something obvious, looks like I ran into some pretty odd stuff here, because as it is, DMA modes for ADC4 don't look very usable if it only works once. What I haven't tried yet is to reset ADC4 and reconfigure it completely after one DMA transfer (in LIMITED mode), but that doesn't sound very practical.
Any help with this (hopefully) now more precise issue is welcome!
2025-01-24 01:43 AM - edited 2025-01-24 01:45 AM
Hello, I worked on this some more and finally found out the culprit. So, here are my findings, if it can help anyone. The LPBAM is not trivial on this MCU range and there were no example available of what I was trying to achieve, especially when using LL.
To sum up:
To work around this, I changed my approach:
Finally, while implementing this approach, I ran into another issue that I also finally figured out:
The autonomous clock for SRAM4 is enabled like so:
LL_SRDAMR_GRP1_EnableAutonomousClock(LL_SRDAMR_GRP1_PERIPH_SRAM4);
So there you go. Hope it can help anyone who would run into similar "issues". I'm going to mark this post as "solution", as the issue is fixed and this post explains how.
2025-01-28 12:15 AM
Hi OpusOne, thanks for sharing.
I am trying something similar.
I have two cases (Mode STOP1, SRAM4, LPDMA1, ADC4 enabled):
The same as yours: monitor one ADC channel with oversampling and wake up the device on AWD (AWD should be computed on the oversampling accumulation only and not the oversampling result).
Monitor two channels with oversampling and circular DMA in order to get only the latest data when the device is woken up externally (I am trying to use DMA in circular mode to save data in an array of 2 items (one for each channel)).
I am having difficulties running LPBAM. The MCU goes to STOP1 but in the first case, it never wakes up. In the second case, the DMA does the job but only once. I get a correct value for the two channels but only for the first time, as expected, but it seems the ADC is stopped.
Can you share your example with me as a starting point?
Thanks for your help
2025-01-28 05:24 PM
For 1., make sure you have enabled the interrupt for AWD (1?), including at the NVIC level, otherwise it won't wake up.
This is how I configure AWD1 (in this example, the thresholds are: low = 0, high = 500):
LL_ADC_SetAnalogWDMonitChannels(ADC4, LL_ADC_AWD1, LL_ADC_AWD_CHANNEL_1_REG);
LL_ADC_ConfigAnalogWDThresholds(ADC4, LL_ADC_AWD1, 500, 0);
LL_ADC_EnableIT_AWD1(ADC4);
LL_ADC_ClearFlag_AWD1(ADC4);
// Interrupts.
NVIC_SetPriority(ADC4_IRQn, 3);
NVIC_EnableIRQ(ADC4_IRQn);
Note that the thresholds passed to LL_ADC_ConfigAnalogWDThresholds() are high first, low second, which was confusing to me, so make sure you passed them in the right order if you use LL.
I haven't tried AWD with oversampling using ADC4 yet - maybe there's also something there that isn't quite configured right.