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.

ADCIntStatus stuck inside interrupt handler



I'm trying to trigger and sample ADC values inside an interrupt handler but it always gets stuck inside the while loop waiting on ADCIntStatus.  

// Trigger the ADC conversion.
ADCProcessorTrigger(ADC1_BASE, ADC_SEQ_0);

// Wait for conversion to be completed.
 while(!ADCIntStatus(ADC1_BASE, ADC_SEQ_0, false))
{
}

// Clear the ADC interrupt flag.
ADCIntClear(ADC1_BASE, ADC_SEQ_0);

// Read ADC Value.
 ADCSequenceDataGet(ADC1_BASE, ADC_SEQ_0, &pVID[3]);

This seems to work for me outside of an interrupt handler but I need to sample the values upon an interrupt.  Is there something I'm missing.  I can't imagine this isn't possible.  It seems to get hung up in or because of the while loop but only when placed inside my ISR.  I place it anywhere else and everything runs.  Inside the ISR it gets stuck.  ????

  • I feel like I had a similar problem using a while loop in an ISR on the Tiva before but was able to remove it.  I can't seem to find a way around it this time.

  • Hello Tim,

    In the ADC Interrupt Handler

    // Wait for conversion to be completed.
    uint32_t ui32ADCIntStatus;
    ui32ADCIntStatus = ADCIntStatus(ADC1_BASE, ADC_SEQ_0, true);

    // Read ADC Value.
    ADCSequenceDataGet(ADC1_BASE, ADC_SEQ_0, &pVID[3]);
    // Set a Global flag
    ui32ADCConversionComplete = 1;
    // Clear the ADC interrupt flag.
    ADCIntClear(ADC1_BASE, ADC_SEQ_0);
    In the main test code
    while(1) {
    // Trigger the ADC conversion.
    ADCProcessorTrigger(ADC1_BASE, ADC_SEQ_0);
    // Wait for conversion to be completed.
    while(!ui32ADCConversionComplete);
    ui32ADCConversionComplete = 0;
    }
    Do remember to map the ADC Interrupt Handler in the startup_ccs.c file
    Regards

    Amit

  • Looks like I neglected to enable one of the two layers of interrupt which kept the interrupt from being signaled.  I've used the ADC comparators until now and it doesn't require the additional interrupt enable call.

    ADCIntEnable(ADC1_BASE, ADC_SEQ_0);

    Didn't realize I needed this second step:
    IntEnable(INT_ADC1SS0);

  • EK TM4C123GXL

    CCS 5.5.0

    I am struggling with what seems like a similar problem. I get stuck in the interrupt handler. But I'm not sure I understand your solution (I'm pretty new to this). The IntEnable(INT_ADC1SS0); doesn't seem like it should be necessary for me and it doesn't seem to fix the issue. I have been able to get single channel ADC to work with this same format, but when I add the additional channels it starts to get stuck.

    Any help would be greatly appreciated. Code I'm using is below:

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/adc.h"

    int main(void)
    {
        uint32_t ui32ADC0Value[4];
        volatile uint32_t ui32Accel0;
        volatile uint32_t ui32Accel1;
        volatile uint32_t ui32Accel2;

    //Set Up System
        SysCtlClockSet(SYSCTL_SYSDIV_2|SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

        ADCIntEnable(ADC0_BASE, 0);
        ADCIntClear(ADC0_BASE, 0);// Clear ADC Interrupt

    //Setup for ADC0
        ADCSequenceDisable(ADC0_BASE, 0);

        ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);

        ADCSequenceStepConfigure(ADC0_BASE, 0, 0,ADC_CTL_CH0);//Sequencer Step-0
        ADCSequenceStepConfigure(ADC0_BASE, 0, 1,ADC_CTL_CH1);//Sequencer Step-1
        ADCSequenceStepConfigure(ADC0_BASE, 0, 2,(ADC_CTL_CH2|ADC_CTL_IE|ADC_CTL_END));//Sequencer Step-2

        ADCSequenceEnable(ADC0_BASE, 0);

            ADCProcessorTrigger(ADC0_BASE, 0);// Trigger ADC Interrupt

            while(!ADCIntStatus(ADC0_BASE, 0, false)) //Wait for interrupt Status flag to go off
                {
                }

                ADCSequenceDataGet(ADC0_BASE, 0, ui32ADC0Value);//Grab the Entire FIFO

                ui32Accel0=3+ui32ADC0Value[0];
                ui32Accel1=4+ui32ADC0Value[1];
                ui32Accel2=5+ui32ADC0Value[2];
    }

  • Hello KC,

    The ADC Cannot work correctly if the System Clock is less than the ADC Functional clock of 16MHz. In the code above the System Clock is set as Crystal Clock of 16MHz divided by 2. You would need to change that to atleast 16MHz.

    Regards

    Amit

  • Amit, thank you for the response.

    I updated and tried a few things, including changing to "DIV1" and going to 24 MHZ. Unless I am misunderstanding the syntax, there is no change in the behavior. It still gets stuck waiting in the interrupt handler.

    In reading the Driver Library, its not entirely clear to me that the format for the SysCtlClockSet is correct. However, I tried a few alternatives with no luck. I also took the SysCtlClockSet out completely with no change in response. I noticed in the example on p.42, that they do not explicitly set the clock when using the ADC, but perhaps its a built in assumption.

  • Hello KC,

    If the code is getting stuck in the IntDefaultHandler, then I would suggest removing the following line of code

    ADCIntEnable(ADC0_BASE, 0);

    What surprises me is that if the IntEnable(INT_ADC0SS0) has never been called by your code, then it should not go to interrupt handler at all.

    Regards

    Amit

  • Hello KC,

    I ran your test code and it actually was going into FaultISR. So what I did was add a small delay loop after enabling the clock to the ADC0.

    Also one very important thing is that the IO's for ADC have not been configured to be ADC Analog Pins. You would have to do that as per the example code given in TIVAWare.

    See code below:

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/adc.h"

    int main(void)
    {
        uint32_t ui32ADC0Value[4];
        volatile uint32_t ui32Accel0;
        volatile uint32_t ui32Accel1;
        volatile uint32_t ui32Accel2;

        //Set Up System
        SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        SysCtlDelay(10);

        ADCIntEnable(ADC0_BASE, 0);
        ADCIntClear(ADC0_BASE, 0);// Clear ADC Interrupt

        //Setup for ADC0
        ADCSequenceDisable(ADC0_BASE, 0);

        ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);

        ADCSequenceStepConfigure(ADC0_BASE, 0, 0,ADC_CTL_CH0);//Sequencer Step-0
        ADCSequenceStepConfigure(ADC0_BASE, 0, 1,ADC_CTL_CH1);//Sequencer Step-1
        ADCSequenceStepConfigure(ADC0_BASE, 0, 2,(ADC_CTL_CH2|ADC_CTL_IE|ADC_CTL_END));//Sequencer Step-2

        ADCSequenceEnable(ADC0_BASE, 0);

        ADCProcessorTrigger(ADC0_BASE, 0);// Trigger ADC Interrupt

        while(!ADCIntStatus(ADC0_BASE, 0, false)) //Wait for interrupt Status flag to go off
        {
        }

        ADCSequenceDataGet(ADC0_BASE, 0, ui32ADC0Value);//Grab the Entire FIFO

        ui32Accel0=3+ui32ADC0Value[0];
        ui32Accel1=4+ui32ADC0Value[1];
        ui32Accel2=5+ui32ADC0Value[2];

        while(1);
    }

    Regards

    Amit

  • Amit-

    Thank you for the insight. I have been walking through the code you provided to try to understand the differences and changes. From what I can tell, the fundamental difference is that you used a PLL clock and I was using the OSC clock. Early on I was able to run the same code for a single input with the OSC clock. I'm curious what could be causing the multi-input version to have problems with the interrupt handler when using the OSC clock. 

    I also ran into another unusual problem. When using your code with the PLL clock all worked fine. Then when I switched to OSC (at the same clock speed) it immediately starting hanging up in the interrupt handler again. But when I switched the code back to the PLL clock and tried to run again, it still kept getting hung up. I tried several times with the same result. I turned off CCS and back on with the PLL code in there and it still hung. It wasn't until I turned off CCS and unplugged the USB cable to the device (then plugged back in, turned on CCS) that the PLL based code would start working again. It was almost like the changes I was making in the code weren't getting into the device. - obviously this made debugging kind of tough....

    You also mentioned:

    Also one very important thing is that the IO's for ADC have not been configured to be ADC Analog Pins. You would have to do that as per the example code given in TIVAWare.

    I searched the users guide, the peripheral library and the workshop manual, but was unable to find any reference to code necessary to configure for analog input. Am I missing something...?

    thanks again for your help

    Keith

  • Hello KC,

    There is an errata on ADC Clock Source and System Clock Source both being Main Oscillator. I think that you are running into that issue when you change the System Clock Source.

    For IO Configuration for ADC Function you need to do the following. Please note that in this case I am using PE7 that corresponds to Analog Channel 20.

        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_7);

    For the case you have you would need to check the Signal Description Chapter of the ADC Sub Section and then select the Analog Channel Pin.

    Regards

    Amit

  • Amit-

    Thanks for the pointer on the ADC section. I had been using primarily the "TivaWare™ Peripheral Driver Library" in which I didn't see the GPIOPinTypeADC reference.

    I added the Enable and the PinType declaration. However had some errors I have not been able to pin down.

    I am using AIN1 which is PE2 (which I believe means it is Pin #2?).

    I get the following errors. First it tells me it is implicitly declared. Second it tells me "GPIO_PIN_2" is undefined. Maybe I have a syntax error but have check both the manuals and other peoples examples here and have not been able to figure it out.

    Description    Resource    Path    Location    Type
    #20 identifier "GPIO_PIN_2" is undefined    main.c    /lab5    line 39    C/C++ Problem

    Description    Resource    Path    Location    Type
    <a href="file:/C:/ti/ccsv5/tools/compiler/dmed/HTML/225.html">#225-D</a>  function "GPIOPinTypeADC" declared implicitly    main.c    /lab5    line 39    C/C++ Problem

    CODE:

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);

    Thanks

    Keith

  • You need to include the GPIO drivers too now.

    #include "inc/hw_gpio.h"

    #include "driverlib/gpio.h"

    A easy way to remember wich includes to use with TivaWare is, "wich words my fuctions start with?" since the ones that need GPIO always need to include gpio.h, ones that use SysCtl need sysctl.h. At leas that's what i do

  • thank you

    I had one but not the other.

  • i'm glad i could help