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.

TMS320F280049C: Interrupt function not called for ADC-C post processing for Limit detection

Part Number: TMS320F280049C
Other Parts Discussed in Thread: C2000WARE

I am working on a project and I need to detect if the adc measurements are above a certain value and then take some further action.

All the interrupts work well but the interrupt function for the ADC-C post processing for limit detection is not been called although the PI Enable and Flag are been set.  What can be the problem or is there something I am missing.  The Code is for the initialization of the post processing is  below

/**< Interrupts that are used in this example are re-mapped to ISR functions found within this file. */
Interrupt_register(INT_ADCC_EVT, &adc::adcCEventISR);

/**< configure trip for SOC0 for battery measurement c0 = batt_curr, c1 = batt_volt */
ADC_setupPPB (ADCC_BASE, ADC_PPB_NUMBER1, ADC_SOC_NUMBER0);
ADC_setPPBTripLimits (ADCC_BASE, ADC_PPB_NUMBER1, 3000, 0);
//ADC_enablePPBEvent (ADCC_BASE, ADC_PPB_NUMBER1, ADC_EVT_TRIPHI);
ADC_enablePPBEventInterrupt (ADCC_BASE, ADC_PPB_NUMBER1, ADC_EVT_TRIPHI);
ADC_clearPPBEventStatus (ADCC_BASE, ADC_PPB_NUMBER1, (ADC_EVT_TRIPHI | ADC_EVT_TRIPLO | ADC_EVT_ZERO));

ADC_setupPPB (ADCC_BASE, ADC_PPB_NUMBER2, ADC_SOC_NUMBER1);
ADC_setPPBTripLimits (ADCC_BASE, ADC_PPB_NUMBER2, 2900, 0);
//ADC_enablePPBEvent (ADCC_BASE, ADC_PPB_NUMBER2, ADC_EVT_TRIPHI);
ADC_enablePPBEventInterrupt (ADCC_BASE, ADC_PPB_NUMBER2, ADC_EVT_TRIPHI);
ADC_clearPPBEventStatus (ADCC_BASE, ADC_PPB_NUMBER2, (ADC_EVT_TRIPHI | ADC_EVT_TRIPLO | ADC_EVT_ZERO));


/**< enable higher level interrupt*/
Interrupt_enable(INT_ADCC_EVT);

The ADC-C measurements operates as expected but the interrupt function for the post processing is not been called. I assume the line below was not successful in the initialization 

Interrupt_register(INT_ADCC_EVT, &adc::adcCEventISR);

Thanks

  • Hi Abayomi,

    I'd recommend examining the ADC and PIE registers in the expressions window after the code is running to determine where in the chain the logic is failing.  You can check:

    • Do the raw ADC result registers for ADC-C have the expected values? (adc result0 > 3000, adc result1 > 2900)?
    • Does the PPB result register match the expected ADC result? (ppb result 1 = adc result 0, ppb result 2 = adc result 1)?
    • Is the PPB trip high flag set for both PPB1 and PPB2? 
    • Is the ADC-C PPB interrupt flag set in the PIE?
    • Does the PIE vector for ADC-C PPB match the address of the intended PPB ISR? 

    This should give you a pretty good idea of what is going wrong an which function calls to re-examine.  

  • I have checked and it is like all the conditions are met.  

    Enclosed are snapshoots from the debugger

    I am not very sure of the below point

    • Does the PIE vector for ADC-C PPB match the address of the intended PPB ISR? 

    Is the snapshot i sent okay.  I think the interrupt routine is not called but why I do not know.  Thanks and I await your reply

  • Hi Abayomi,

    Good work on the screenshots; it definitely seems like the ADC + PPB are working and everything is enabled from the ADC side.

    Since the flag is set and pending in the PIE map, I think it means that something is not enabled in the PIE or CPU to accept the ISR.  Have a look at your code that is doing the below initializations (or bitfield equivalent) and make sure you don't have any instances of ADC-A where it should be ADC-C.  You can also go investigate these initializations in the expressions window to make sure they went through.

    Based on the symptoms, it seems like something is not enabled in the PIE/CPU ISR chain.  If you had mapped the wrong ISR or an invalid ISR location, your code would probably "run off into the weeds" or possibly hit an invalid vector breakpoint.  

        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        //
        // Map ISR functions
        //
        Interrupt_register(INT_ADCC_EVT, &adcCEvtISR);
    
        //
        // Enable specific PIE & CPU interrupts:
        //
        Interrupt_enable(INT_ADCC_EVT);

  • Hello Devin,

    Thanks for your reply.  I have checked the areas you asked me to check and it seens all looks good.  

    I am enclosing a snapshot for you to also have a look at the interupt vector address.

    What could be the probelm or where else can i look at.  I have looked at all sections of the code but i have not seen anything strange.

    Could it be because i am writing in C++.  I converted the interrupt function to c but it was still not called.

    Thanks

  • Hi Abayomi,

    I think there is also a global CPU interrupt (INTM bit in the CPU ST1 register : 0 = "enabled").  Do you have other interrupts that are working?  The macro "EINT" should be able to enable this.

    You can also check the individual (CPU, not PIE) interrupt enables (and flags) via the IER and IFR registers in the CPU (not PIE).  

  • Hi Devin,

    Thanks for your reply.

    The other interrupts are working (ADC-a, ADC-b, ADC-c, Timer1, Timer2 and DMA).  

    By individual (CPU, not PIE ) interrupt.  Where can I find that?  Do you mean ADC-C interrupt register? or some other register?  Is it the snapshot i enclosed belod

    I eagerly await your reply.  Thanks

  • Hi Abayomi,

    There are 3 levels for an interrupt

    • Peripheral (in this case ADC)
    • PIE
    • CPU

    I think you've established that the interrupt flag is pending in the PIE (which means it is also working in the peripheral) but you still need to investigate the CPU.

    The way the PIE (peripheral interrupt expansion) works is that multiple PIE interrupts get mapped to a single CPU interrupt.  For example PIE 1.1 = ADC-A INT1, PIE 1.2 = ADC-B INT1, and PIE 1.3 = ADC-C INT1 all go to CPU INT1.  PIE 2.1, 2.2, 2.3, etc. all go to CPU INT2.  

    Since you ADC-C EVT Interrupt goes to PIE channel 10.9, you'd want to also check that CPU interrupt 10 is enabled.  CPUT interrupt 10 is enabled in the "IER" register of the CPU.  This IER register is a CPU register and not associated with the PIE or PIE registers.  

    There is also a global interrupt enable bit in the CPU in CPU register ST1 (but if you already have other working interrupts, there is no reason to believe this isn't set).  

  • Good morning Devin,

    Thanks for your detailed feedback.  I would like to ask what next are my options.  From the above we have been able to establish that the program works as expected but the interrupt is not still been called.  Where should i possibly still look into.

    I am using the following hardware and software resources for the project

          Launchxl- F280049c development kit with number 15C1928000640

          C2000ware_3_03_00_00

    Can I send you the entire

    Or does the lauchpad need a SW update? I would be willing to 

    Thanks

  • Hi Abayomi,

    Just to be extremely explicit, can you check that INT line 10 (the line for ADC-C EVT) is enabled in the CPU in the IER?  This is not the same as the PIE IER register:

  • Hi Devin,

    I checked.  The bit is set.  The snapshot is below

    The entire code for the configuration of my ADC-C module is below

    void adc::InitADCGrpC(void)
    {

    /**< adc measurements of voltages and currents on module c */

    /**< reset the peripheral */
    SysCtl_resetPeripheral(SYSCTL_PERIPH_RES_ADCC);

    /**< enable the peripheral */
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ADCC);

    EALLOW;
    AnalogSubsysRegs.ANAREFCTL.bit.ANAREFASEL = 0; //TODO configuration is for 100 pin f28004x type
    AnalogSubsysRegs.ANAREFCTL.bit.ANAREFBSEL = 0;
    AnalogSubsysRegs.ANAREFCTL.bit.ANAREFCSEL = 0;
    EDIS;

    /**< disable the peripheral */
    ADC_disableConverter(ADCC_BASE);

    /**< Setup VREF as internal */
    ADC_setVREF(ADCC_BASE, ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V);

    /**< Set ADCCLK divider to 100MHz/4 */
    ADC_setPrescaler(ADCC_BASE, ADC_CLK_DIV_4_0);

    /**< Set pulse positions to late */
    ADC_setInterruptPulseMode(ADCC_BASE, ADC_PULSE_END_OF_CONV);


    /**< Power up the ADCs and then delay for 1 ms */
    ADC_enableConverter(ADCC_BASE);

    DEVICE_DELAY_US(1000); //consider grouping them together

    }

    void adc::InitADCGrpCSOCs(void)
    {
    /**< Configure SOCs of ADCC */
    /**< SOC0 will convert pin c0 = batt_curr, c1 = batt_volt, c2 = il1pfc, c3 = il2pfc, c4 = vsuppply, with a sample window of 10 SYSCLK cycles sample window. */
    ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY, ADC_CH_ADCIN0, (uint32_t)ADC_SAMPLE_WINDOW);
    ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_SW_ONLY, ADC_CH_ADCIN1, (uint32_t)ADC_SAMPLE_WINDOW);
    ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER2, ADC_TRIGGER_SW_ONLY, ADC_CH_ADCIN2, (uint32_t)ADC_SAMPLE_WINDOW);
    ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER3, ADC_TRIGGER_SW_ONLY, ADC_CH_ADCIN3, (uint32_t)ADC_SAMPLE_WINDOW);
    ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER4, ADC_TRIGGER_SW_ONLY, ADC_CH_ADCIN4, (uint32_t)ADC_SAMPLE_WINDOW);

    /**< Set priority type */
    ADC_setSOCPriority(ADCC_BASE, ADC_PRI_ALL_ROUND_ROBIN);

    /**< interrupt triggered by the soc4 */
    ADC_setInterruptSource(ADCC_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER4);

    /**< enable interrupt for the adc module */
    ADC_enableInterrupt(ADCC_BASE, ADC_INT_NUMBER1);

    /**< sure its flag is cleared. */
    ADC_clearInterruptStatus(ADCC_BASE, ADC_INT_NUMBER1);

    /**< Interrupts are re-mapped to ISR functions */
    Interrupt_register(INT_ADCC1, &adc::adcCISR);

    /**< enable higher level interrupt*/
    Interrupt_enable(INT_ADCC1);

    /**< Post-processing block */
    /**< configure adc to generate events if measured values raises above or sinks below limits */

    /**< Interrupts that are used in this example are re-mapped to ISR functions found within this file. */
    Interrupt_register(INT_ADCC_EVT, &adc::adcCEventISR);

    /**< configure trip for SOC0 for battery measurement c0 = batt_curr, c1 = batt_volt */
    ADC_setupPPB (ADCC_BASE, ADC_PPB_NUMBER1, ADC_SOC_NUMBER0);
    ADC_setPPBTripLimits (ADCC_BASE, ADC_PPB_NUMBER1, 3000, 0);
    //ADC_enablePPBEvent (ADCC_BASE, ADC_PPB_NUMBER1, ADC_EVT_TRIPHI);
    ADC_enablePPBEventInterrupt (ADCC_BASE, ADC_PPB_NUMBER1, ADC_EVT_TRIPHI);
    ADC_clearPPBEventStatus (ADCC_BASE, ADC_PPB_NUMBER1, (ADC_EVT_TRIPHI | ADC_EVT_TRIPLO | ADC_EVT_ZERO));

    ADC_setupPPB (ADCC_BASE, ADC_PPB_NUMBER2, ADC_SOC_NUMBER1);
    ADC_setPPBTripLimits (ADCC_BASE, ADC_PPB_NUMBER2, 2900, 0);
    //ADC_enablePPBEvent (ADCC_BASE, ADC_PPB_NUMBER2, ADC_EVT_TRIPHI);
    ADC_enablePPBEventInterrupt (ADCC_BASE, ADC_PPB_NUMBER2, ADC_EVT_TRIPHI);
    ADC_clearPPBEventStatus (ADCC_BASE, ADC_PPB_NUMBER2, (ADC_EVT_TRIPHI | ADC_EVT_TRIPLO | ADC_EVT_ZERO));


    /**< enable higher level interrupt*/
    Interrupt_enable(INT_ADCC_EVT);


    /**< interrupt triggered by the soc4 */
    ADC_setInterruptSOCTrigger(ADCC_BASE, ADC_SOC_NUMBER4, ADC_INT_SOC_TRIGGER_NONE);
    }

    Thanks for your efforts.  If I need to provide more information.  Please let me know

  • Hi Abayomi,

    Apologies for the delay.  I've read through this code a few times and don't see anything wrong with the ADC-C limit trip code.  (You should probably set the ADCCLK to 100MHz / 2 = 50MHz and not 100MHz / 4 = 25MHz).

    If you reduce this to the minimum ADC-C trip code to reproduce the issue and post the project, I'll try to run it on my side.  I'll also ask a SW engineer to investigate if there are any known quirks when using c++ instead of c.   

  • The change in ADC clock did not solve the issue.  I would try reduce the code to the minimum and then post it.  Did you get a feedback from the engineer abouot the mixing the c++ and c codes?

    Thanks