MSPM0G1507: ADC IRQ is running with IIDX.STAT reading 0

Part Number: MSPM0G1507
Other Parts Discussed in Thread: SYSCONFIG

Tool/software: Theia

Hi, this is my ADC configuration in syscfg:

ADC121.$name = "ADC12_0";
ADC121.repeatMode = true;
ADC121.resolution = "DL_ADC12_SAMP_CONV_RES_10_BIT";
ADC121.powerDownMode = "DL_ADC12_POWER_DOWN_MODE_MANUAL";
ADC121.trigSrc = "DL_ADC12_TRIG_SRC_EVENT";
ADC121.configWinCompHighThld = 500;
ADC121.adcMem0trig = "DL_ADC12_TRIGGER_MODE_TRIGGER_NEXT";
ADC121.enabledInterrupts = ["DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED"];
ADC121.sampleTime0 = "1.4us";
ADC121.adcMem0chansel = "DL_ADC12_INPUT_CHAN_13";
ADC121.subChanID = 1;
ADC121.pubChanID = 2;
ADC121.enabledEvents = ["DL_ADC12_EVENT_MEM0_RESULT_LOADED"];

Later, I set it for single conversion (averaging 128x). 

DL_ADC12_disableConversions(ADC12_0_INST);
          DL_ADC12_initSingleSample(ADC12_0_INST, DL_ADC12_REPEAT_MODE_ENABLED,
                                    DL_ADC12_SAMPLING_SOURCE_AUTO,
                                    DL_ADC12_TRIG_SRC_SOFTWARE,
                                    DL_ADC12_SAMP_CONV_RES_10_BIT,
                                    DL_ADC12_SAMP_CONV_DATA_FORMAT_UNSIGNED);
          DL_ADC12_configConversionMem(ADC12_0_INST, ADC12_0_ADCMEM_0,
                                       DL_ADC12_INPUT_CHAN_13,
                                       DL_ADC12_REFERENCE_VOLTAGE_VDDA,
                                       DL_ADC12_SAMPLE_TIMER_SOURCE_SCOMP0,
                                       DL_ADC12_AVERAGING_MODE_ENABLED,
                                       DL_ADC12_BURN_OUT_SOURCE_DISABLED,
                                       DL_ADC12_TRIGGER_MODE_TRIGGER_NEXT,
                                       DL_ADC12_WINDOWS_COMP_MODE_DISABLED);
          DL_ADC12_setPowerDownMode(ADC12_0_INST,
                                    DL_ADC12_POWER_DOWN_MODE_MANUAL);
          DL_ADC12_configHwAverage(ADC12_0_INST, DL_ADC12_HW_AVG_NUM_ACC_128,
                                   DL_ADC12_HW_AVG_DEN_DIV_BY_128);
          // DL_ADC12_disableConversions(ADC12_0_INST);
          // DL_ADC12_setSampleTime0(ADC12_0_INST,
          // PARAM_Settings[ADC_SAMPLE_TIME]);
          // DL_ADC12_enableConversions(ADC12_0_INST);
          NVIC_ClearPendingIRQ(ADC12_0_INST_INT_IRQN);
          DL_ADC12_clearInterruptStatus(
              ADC12_0_INST, (DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED));
          DL_ADC12_enableInterrupt(ADC12_0_INST,
                                 (DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED));
          DL_ADC12_enableConversions(ADC12_0_INST);

          NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
          DL_ADC12_startConversion(ADC12_0_INST);

I would like to handle the result in my IRQ.

void ADC12_0_INST_IRQHandler(void) {
  volatile static uint16_t adcCaptureCnt;
  int timingError = 0;
  // this IRQ is called only when there is signal
  volatile int interruptResult = DL_ADC12_getPendingInterrupt(ADC12_0_INST);
  switch (interruptResult) {
  case DL_ADC12_IIDX_MEM0_RESULT_LOADED:
    adcResult = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);
    switch (PARAM_State) {
    case READ_DATA: {
      // readback values directly handled in parameterization.c
    } break;
    case CALIBRATION: {
      switch (calibrationType) {
      case DC_CAL: {
        PARAM_Put16BitValue(DC_L, DC_H,
                            adcResult); // eeprom is saved in parameterization.c
        CalInProgress = false;
      } break;
      case OPT_SHORT_CAL: {
        CalInProgress = false;
      } break;
      default:
        break;
      }
    } break;
    .... 

It is very strange that when I set my compiler optimisation to '0', code runs properly. But when I set optimisation to '2', the IRQ runs but with the interruptResult (IIDX.STAT) of 0. Hence, it skips over my code.

The funny thing is when I run the code under Debug using breakpoints within the IRQ, the IRQ actually runs twice, once with interruptResult of 0 and then the second time with the expected interruptResult of 9 (DL_ADC12_IIDX_MEM0_RESULT_LOADED). While it's not ideal, I could live with it. But this behaviour doesn't happen during normal running.

I have already tried to clear all interrupts, pending interrupts, etc. I am not sure what else to do at this point. Setting optimisation to '0' is not an option as I need the optimisation for other parts of the code to run properly. Please help

  • Hi Tan,

    I checked your code, looks okay from my side.

    Some confusing things looks you have overwrite the ADC setting in main source code, as the sysconfig files show different configurations. Can you clean up the sysconfig configration (I see event configuration / event trigger not used) in case there any conflicts.

    It is very strange that when I set my compiler optimisation to '0', code runs properly. But when I set optimisation to '2', the IRQ runs but with the interruptResult (IIDX.STAT) of 0. Hence, it skips over my code.

    The optimization won't impact the hardware interrupt, unless the interrupt setting has some difference, maybe you can check the interrupt related register, RIS/IMASK/MIS, to see any abnormal status occurs (overflow or others).

    The funny thing is when I run the code under Debug using breakpoints within the IRQ, the IRQ actually runs twice, once with interruptResult of 0 and then the second time with the expected interruptResult of 9 (DL_ADC12_IIDX_MEM0_RESULT_LOADED). While it's not ideal, I could live with it. But this behaviour doesn't happen during normal running.

    That's also weird. If it read back as 0, which represent there is no interrupt trigger. Unless when it trigger the interrupt at the time when it clean the interrupt status.

    I do not have much idea on this kind of phenomenon, please do check the register and maybe other inerrupt impact.

    I have create a test project, while nothing show up in my side, all works well with optimization level 2 - no interrupt lost or interrupt multiple entry.

    See below attachment for your reference: ADC_TEST.ZIP

    [Maybe you can try also update the SDK version, in case there has any issues with a pretty old SDK version]

    B.R.

    Sal

  • Some confusing things looks you have overwrite the ADC setting in main source code, as the sysconfig files show different configurations. Can you clean up the sysconfig configration (I see event configuration / event trigger not used) in case there any conflicts.

    OK I can try this. Reason for the "conflict" is because the ADC operates in different configurations, depending on the application needs.

    That's also weird. If it read back as 0, which represent there is no interrupt trigger. Unless when it trigger the interrupt at the time when it clean the interrupt status.

    Exactly, that's what was so confusing to me. 

    Anyway, I am having some other weird race conditions (which may be due to my own coding or interrupt configuration issue, of course). If you are aware of any known issues with interrupt triggering (particularly timer or ADC), please let me know.

  • Hi Tan,

    The interrupt missed issues, maybe you can also check whether there always has high priority pending interrupt which block ADC interrupt access.

    You can check some of below method:

    1. Disable other interrupt.

    2. Check ADC IMASK/RIS/MIS status and check ADC memeory result to verify whether ADC has been correctly enabled and finish the converion. Maybe there has some error for ADC enable flow.

    B.R.

    Sal

  • My apologies. I had forgotten to declare a variable in my own application as "volatile" Weary. This caused my code to not work. Nothing is wrong with the MCU itself. Lesson learned: have to be careful to declare as "volatile" variables which are manipulated in both ISR and main loop.

    The different reconfigurations of the ADC does not cause any issues with the interrupt. Perhaps the "wrong" value of DL_ADC12_getPendingInterrupt(ADC12_0_INST); is a debugger artefact of optimised code but that caused me to look into the wrong direction for some time.

  • Hi Tan,

    Glad to hear you have solved the issues.

    This aspect is easily overlooked.

    B.R.

    Sal