cdebuggingmicrocontrollercortex-m

SAMR21 skipping parts of code while debugging


My code should read the ADC 3 times, then take the average, if it is less than half of the fullscale value, the the onboard LED should turn off, if it is higher than half of the fullscale value it should turn on.

The ADC part works as far as I can tell by debugging, it takes the measurements as it should, but when I get into the part that compares the values, the code skips the part of turning the LED on or off and it goes back to the start of the main loop, then it goes back to the while(1) loop (all of this using the step over button on Atmel Studio)

Here's the code:


/*
 * Include header files for all drivers that have been imported from
 * Atmel Software Framework (ASF).
 */
/*
 * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
 */
#include <asf.h>


int main (void)
{
    system_init();
    uint32_t result = 0;
    uint8_t samp = 0;
    
    PORT->Group[0].DIRSET.reg |= 1<<19;
    
    ADC->DBGCTRL.reg = 1;
    
    SYSCTRL->OSC8M.reg |= 1<<30 | 1<<6 | 0b10;
    
    //ADC Pin6 Config
    PORT->Group[0].DIRCLR.reg |= 1<<6;
    PORT->Group[0].PMUX[3].reg = 0x1;
    PORT->Group[0].PINCFG[6].reg &= ~(0b11);
    PORT->Group[0].PINCFG[6].reg |= 1;
    
    //ADC CLK Config
    PM->APBCMASK.reg |= PM_APBCMASK_ADC; //Enable clk bus
    
    
    /* Enable GCLK1 for the ADC */
    GCLK->GENDIV.reg = 0;
    
    while (GCLK->STATUS.bit.SYNCBUSY) {};
    GCLK->GENCTRL.reg = 1<<21 | 1<<19 | 1<<17 | 1<<16 | 1<<10 | 1<<9;
    while (GCLK->STATUS.bit.SYNCBUSY) {};
        
    GCLK->CLKCTRL.reg = 1<<14 | 0x1E;

    /* Wait for bus synchronization. */
    while (GCLK->STATUS.bit.SYNCBUSY) {};
    
    uint32_t bias = (*((uint32_t *) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos;
    uint32_t linearity = (*((uint32_t *) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
    linearity |= ((*((uint32_t *) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;

    /* Wait for bus synchronization. */
    while (ADC->STATUS.bit.SYNCBUSY) {};

    /* Write the calibration data. */
    ADC->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | ADC_CALIB_LINEARITY_CAL(linearity);
    
    /* Wait for bus synchronization. */
    while (ADC->STATUS.bit.SYNCBUSY) {};

    /* Use the internal VCC reference. This is 1/2 of what's on VCCA.
       since VCCA is typically 3.3v, this is 1.65v.
    */
    ADC->REFCTRL.reg = 2;

    /* Only capture one sample. The ADC can actually capture and average multiple
       samples for better accuracy, but there's no need to do that for this
       example.
    */
    ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1;

    /* Set the clock prescaler to 512, which will run the ADC at
       8 Mhz / 512 = 31.25 kHz.
       Set the resolution to 12bit.
    */
    while (ADC->STATUS.bit.SYNCBUSY) {};
    ADC->CTRLB.reg = 0;

    /* Configure the input parameters.

       - GAIN_DIV2 means that the input voltage is halved. This is important
         because the voltage reference is 1/2 of VCCA. So if you want to
         measure 0-3.3v, you need to halve the input as well.

       - MUXNEG_GND means that the ADC should compare the input value to GND.

       - MUXPOST_PIN3 means that the ADC should read from AIN3, or PB09.
         This is A2 on the Feather M0 board.
    */
    while (ADC->STATUS.reg == STATUS_BUSY) {}
    ADC->INPUTCTRL.reg = 0b1111<<24 | 0b11 << 11 | 6;
    /* Wait for bus synchronization. */
    while (ADC->STATUS.bit.SYNCBUSY) {};

    /* Enable the ADC. */
    ADC->CTRLA.reg = 0b10;
    /* Wait for bus synchronization. */
    while (ADC->STATUS.bit.SYNCBUSY) {};


    while (1) {
        
        while (ADC->STATUS.bit.SYNCBUSY) {};
        /* Wait for the result ready flag to be set. */
        ADC->SWTRIG.bit.START = 1;
        while(ADC->INTFLAG.bit.RESRDY == 0){};
        
        /* Clear the flag. */
        ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY;

        /* Read the value. */
        result += ADC->RESULT.reg;
        samp++;

        if(samp >= 3){
            if((result/3) < 2045){
                PORT->Group[0].OUTSET.reg |= 1<<19;
            }   
            else{
                PORT->Group[0].OUTCLR.reg |= 1<<19;
            }
            
            result = 0;
            samp = 0;
        }
            
        
    }
        
}


Tried debugging going line by line, expected the PORT->Group[0].OUT lines to execute, but lines do not execute and the code jumps to the start of main(), then it jumps to the start of while(1)


Solution

  • During the development and debugging phases of a project, though, it is always good practice to disable all optimizations as they might modify the structure of the code being analyzed and render single-stepping and breakpoint placement problematic.

    BUT:

    Please always be very careful if you test a different code than you release. As NASA says:

    "test what you fly, fly what you test."