This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSPM0G3507: ADC does not propperly start and stop

Part Number: MSPM0G3507

ADC_with_DMA_stop_and_start_issues.pdf adc_with_dma_start_stop_issue.zip 

Hello,

in the attached files we have discribed our issue with the adc and added also some example code.

Please have a look on it and explain or recommend steps to fix the behavior.

BR

Norbert

  • Hi Norbert,

    I need some time to check the details carefully, it does have a lot things inside the document.

    Thanks for your patience.

    B.R.

    Sal

  • Hi Norbert,

    For the first case, where users clear ENC bit, it can been seen that the ADC execute the conversion for some reason.

    I have a guess below:

    After ENC is clear, the ADC is active to next trigger signal. If all the channels are configured require valid trigger, then it will convert one following channel. If only the last channel configured as valid trigger, then it will end at the last channel.

    To quick verify it, I suggest you read the RIS bit to see if MEM3 is loaded if you clear ENC after MEM0 and before MEM1. -> Make sure in DMA done interrupt, you will clear RIS bit of MEM0~MEM3 (channel 0~3).

    -> If the suspect is correct, only the MEM2 will be set with next timer trigger. The MEM3 will never be set.

    B.R.

    Sal

  • As for the workaround, I have some proposal below:

    #1 Add DMA disable in ADC module

    Add below:

    DL_ADC12_disableDMATrigger(ADC1, DL_ADC12_DMA_MEM0_RESULT_LOADED << (num_of_samples-1));  // trigger on last sample

    DL_ADC12_disableDMA(ADC1);

    to disable DMA transfer in ADC module also.

    Note:

    I see you mentioned related thing in the doc, but I do not see the disable behavior in the ADC_stop().

    #2 Stop Timer Event Generation to disable ADC conversion

    stop timer -> DL_TimerG_disableEvent -> enable timer.

    Directly disable event might work without stopping timer.

    #3 Reset ADC and Re-configure ADC

    To stop ADC:

    clear ENC bit, reset ADC

    To start ADC:

    enable ADC power, configure ADC with preset parameters, set ENC bit to receive Timer trigger event

    B.R.

    Sal

  • ADC_Start

    Hello Sal, thank you for your answers!

    I'm a colleague of Norbert's.

    After ENC is clear, the ADC is active to next trigger signal. If all the channels are configured require valid trigger, then it will convert one following channel. If only the last channel configured as valid trigger, then it will end at the last channel.

    Yes, that is something we've seen as well and shown in the screenshots. The problem was rather in the unclear documentation of this behavior in the reference manual that led to much time spent on investigating the root cause of the side effects it causes. Should we expect the update of the manual with clarified explanations? The second point of "Main questions" is still open as well.

    As for the workaround, I have some proposal below

    Can you please clarify if these workarounds are related to the first or the second problem?

    #1 Add DMA disable in ADC module

    In our example, we are disabling the DMA channel in ADC_Stop() and (in the second, "fixed", example), clearing the pending DL_ADC12_DMA_MEM3_RESULT_LOADED before enabling the channel in ADC_Start(). What creates the necessity to disable the DMA trigger as well, and what problems should it fix? We would like to have a deeper understanding of the system to address potential future problems more effectively.

    #2 Stop Timer Event Generation to disable ADC conversion

    As I understand, it is a potential "replacement" for ADC_Stop(), right? To stop the triggering, instead of forcing ADC to stop conversions? While this is a robust approach, we still would like to concentrate on the ways to stop ADC itself, without interacting with the peripherals that trigger it.

    #3 Reset ADC and Re-configure ADC

    This is the approach we want to avoid in our system. ADC configuration must remain untouched while we are restarting it.

    The answers to the questions from the document ("Main questions", "Side questions and clarification") are in progress, and we should expect them sometime later, right?

    Please let us know if something is unclear or unreproducible from the prepared document or code example.

    BR,
    Oleksandr

  • Hi Oleksandr,

    Should we expect the update of the manual with clarified explanations? The second point of "Main questions" is still open as well.

    Sure, I will discuss internally to see how to add additional clarifications on this part. Maybe an application note is preferred as this is a unique application scenario. Please let me know if there any new findings from you side on this case.

    Can you please clarify if these workarounds are related to the first or the second problem?

    The workarounds is proposed to fix this specical issues: disable ADC conversion just before the last channel which trigger the DMA done interrupt, might result in a interrupt timing conflict on software logic.

    What creates the necessity to disable the DMA trigger as well, and what problems should it fix? We would like to have a deeper understanding of the system to address potential future problems more effectively.

    The root cause is not clear for now. I will do some experiment test to dig more details and I am appericated if you can share some findings towards the proposal.

    The answers to the questions from the document ("Main questions", "Side questions and clarification") are in progress, and we should expect them sometime later, right?

    Yes, while I now prioritize the ADC ENC behavior and DMA trigger logic research.

    The issues about the second question -> interrupt lost, I can check later whent the first problem is clear clarified. -> I think if the first problem saved, we might not encounter the second problem and we can dig it later.

    B.R.

    Sal

  • The root cause is not clear for now. I will do some experiment test to dig more details and I am appericated if you can share some findings towards the proposal.

    Understood, thank you for the clarification. I've tested this proposal and see the same behavior as in the "second" implementation of ADC_Stop -> ADC is stopped, I don't observe the redundant interrupts after the stop function is called. However, the second issue is still there: at a random point in time, ADC is not started again after the start function and stuck in the state described in "Second problem faced (conditions to reproduce are unclear)" of the attached document

    We will wait for further clarifications from your side and let you know in case of additional findings.

    BR,
    Oleksandr

  • Hi Oleksandr,

    Thanks for the feedback, I'll take a look into these two issues.

    B.R.

    Sal

  • Hi Sal!
    Any updates on this?

    BR,
    Oleksandr

  • Hello,

    when can we expect some feedback here.
    the implementation is currently blocked on our side.

    Please provide a timeline when we can expact some feedback.

    Many Thanks,

    Alex

  • Hi Alex, Oleksandr,

    Sorry for the late response. I'll prioritize it and update early next week.

    B.R.

    Sal

  • Hi Alex, Oleksandr,

    I have done some experiment to analyze this issues deeply.

    For the ADC behavior in sequence mode (valid trriger required for next conversion), it has below observations:

    1. When ADC is disabled in sequence mode, it is active to next trigger signal, and will be inactive to the other following trigger signal

    2. When ADC is disabled in sequence mode, it might have on-going conversion (current unfished conversion, and next active conversion) and then the event (to interrupt or to DMA) is generated

    3. When ADC is disabled in sequence mode, and then enable, the following conversion start from MEM0, but it will stop at middle of the sequence mode. This means, the ADC conversion counting is not cleared with ADC disable. So the ENC automatically cleared in the middle of the ADC conversion

    3.a The issue #3 only occurs if users does not disable event properly, if users clear event trigger properly, then no issue remains.

    4. When ADC is disabled in sequence mode, and if there has on-going event continously, then there will pending with 1 event for adc conversion. And after ADC enabled, the conversion start from MEM0 immediately one time, and then wait for the trigger signal.

    So, users can not immediately stop ADC. And should add some additional operation to process the ADC/DMA states.

    I have create an recommended flow attached:

    void USER_ADC_STOP(void){
        // stop event
        DL_TimerG_disableEvent(TIMER_0_INST, DL_TIMERG_EVENT_ROUTE_1, (DL_TIMERG_EVENT_ZERO_EVENT));
        // stop adc
        DL_ADC12_disableConversions(ADC1);
        gEnableADC = false;
    }
    
    void USER_ADC_START(void){
        // enable dma
        if(!DL_DMA_isChannelEnabled(DMA, DMA_CH0_CHAN_ID)){
            DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID,
                (uint32_t) DL_ADC12_getMemResultAddress(ADC12_0_INST, DL_ADC12_MEM_IDX_0));
            DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t) &gADCSamples[0]);
            DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, ADC_SAMPLE_SIZE);
            DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
        }
        // start adc
        gEnableADC = true;
        DL_ADC12_enableConversions(ADC1);
        // start event
        DL_Timer_clearEventsStatus(TIMER_0_INST, DL_TIMERG_EVENT_ROUTE_1, (DL_TIMERG_EVENT_ZERO_EVENT));
        DL_TimerG_enableEvent(TIMER_0_INST, DL_TIMERG_EVENT_ROUTE_1, (DL_TIMERG_EVENT_ZERO_EVENT));
    }
    
    void ADC12_0_INST_IRQHandler(void)
    {
        switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
            case DL_ADC12_IIDX_DMA_DONE:
                /* gCheckADC++; */
                if(gEnableADC){
                   /* configure DMA&ADC to start next transfer */
                }
                break;
            default:
                break;
        }
    }

    Generally, I think the messed up event system results in some unexpected observation.

    B.R.

    Sal    

  • Hi Sal!

    Thank you for your research.

    Your 1st and 2nd points are clear -- they correspond to the "First problem faced" from our document, right? The solution is basically to ignore the possible last IRQ with the software flag.

    The 3rd point explains the "Second problem faced" from our document? I will try to rephrase it to check if I got it right:

    Under unfortunate timings, due to the messed-up event system results (HW bug, I assume?), when we stop ADC in the middle of conversion, the internal counter is not cleared. After ADC is started again, conversion starts from MEM0 and lasts not for the configured number of conversions, but for the amount left in the internal counter, so the trigger to DMA is not generated, we never go to the IRQ handler to prepare a new sequence, and we see that the system is stuck?
    Will this be investigated further by the design team and described in future errata revisions? This might have a high impact on applications that are using ADC, or even be a bigger problem of the event publishing system that affects more peripherals.

    Using the example we shared, I can confirm that the second issue is not reproducible after applying enabling/disabling of the timer event.

    But as ADC can be subscribed to any event, not necessarily timers, what is the impact in this case? I've shortly tested a solution, where I replaced DL_TimerG_enableEvent with DL_ADC12_setSubscriberChanID(timerID) and DL_TimerG_disableEvent  with DL_ADC12_setSubscriberChanID(0), and the issue did not reproduce so far. Is it a suitable substitute for disabling the event publisher?

    The 4th point is new and relates rather to the synchronization of the trigger and the sequence? Is the pending event cleared by DL_Timer_clearEventsStatus?

    BR,
    Oleksandr

  • Hi Oleksandr,

    Your 1st and 2nd points are clear -- they correspond to the "First problem faced" from our document, right? The solution is basically to ignore the possible last IRQ with the software flag.

    Yes, we need process the on-going ADC conversion if we really hit the conversion window (us level). The interrupt is expected to be triggered and the stop.

    The 3rd point explains the "Second problem faced" from our document? I will try to rephrase it to check if I got it right:

    Yes, that is my suspect.

    Will this be investigated further by the design team and described in future errata revisions?

    Yes, I have the #3 issue example for internal design team discussion. -> ongoing.

    For this suspection, I need doe more test cases and then discuss with design team. -> I'll follow up when I back office. I am OOO for business travel next two weeks.

    But as ADC can be subscribed to any event, not necessarily timers, what is the impact in this case? I've shortly tested a solution, where I replaced DL_TimerG_enableEvent with DL_ADC12_setSubscriberChanID(timerID) and DL_TimerG_disableEvent  with DL_ADC12_setSubscriberChanID(0), and the issue did not reproduce so far. Is it a suitable substitute for disabling the event publisher?

    It looks good. As if the EVENT Channel is disabled (set with 0), even though the timer is contiously generating event, ADC does not subscribe it and its internal event system keeps no changing.

    The 4th point is new and relates rather to the synchronization of the trigger and the sequence? Is the pending event cleared by DL_Timer_clearEventsStatus?

    I think this is a mess inside the ADC event system, as the event coming from timer every PWM cycle, while ADC conversion is disabled to process the trigger event.

    And DL_Timer_clearEventsStatus does not help.

    B.R.

    Sal

  • Thank you, Sal!

    For now, I will apply the mentioned workarounds (IRQ ignoring and unsubscribing from trigger event), and we will wait for the new insights from you or the new errata release with the official workaround.

    BR,
    Oleksandr