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.

MSP432P401R: Multiple Channel Sample without Repeat only returns the first two values

Part Number: MSP432P401R


Hey,

I am trying to use the Multiple Channel Sample without Repeat example. But i'm running in to some trouble with the MAP_ADC14_getMultiSequenceResult(resultsBuffer); function. 

it only changes the first two values in the resultsBuffer. I am using the exact example as found in the resource explorer. So I don’t get why it’s not working. Here is the example code I used:

/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

/* Standard Includes */
#include <stdint.h>

#include <string.h>

static uint16_t resultsBuffer[8];

int main(void)
{
    /* Halting WDT  */
    MAP_WDT_A_holdTimer();
    MAP_Interrupt_enableSleepOnIsrExit();

    /* Zero-filling buffer */
    memset(resultsBuffer, 0x00, 8);

    //![Simple REF Example]
    /* Setting reference voltage to 2.5  and enabling reference */
    MAP_REF_A_setReferenceVoltage(REF_A_VREF2_5V);
    MAP_REF_A_enableReferenceVoltage();
    //![Simple REF Example]

    /* Initializing ADC (MCLK/1/1) */
    MAP_ADC14_enableModule();
    MAP_ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_4,
            0);

    /* Configuring GPIOs for Analog In */
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,
            GPIO_PIN5 | GPIO_PIN4 | GPIO_PIN3 | GPIO_PIN2 | GPIO_PIN1
                    | GPIO_PIN0, GPIO_TERTIARY_MODULE_FUNCTION);
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4,
            GPIO_PIN7 | GPIO_PIN6, GPIO_TERTIARY_MODULE_FUNCTION);


    /* Configuring ADC Memory (ADC_MEM0 - ADC_MEM7 (A0 - A7)  with no repeat)
     * with internal 2.5v reference */
    MAP_ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM7, false);
    MAP_ADC14_configureConversionMemory(ADC_MEM0,
            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
            ADC_INPUT_A0, false);
    MAP_ADC14_configureConversionMemory(ADC_MEM1,
            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
            ADC_INPUT_A1, false);
    MAP_ADC14_configureConversionMemory(ADC_MEM2,
            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
            ADC_INPUT_A2, false);
    MAP_ADC14_configureConversionMemory(ADC_MEM3,
            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
            ADC_INPUT_A3, false);
    MAP_ADC14_configureConversionMemory(ADC_MEM4,
            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
            ADC_INPUT_A4, false);
    MAP_ADC14_configureConversionMemory(ADC_MEM5,
            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
            ADC_INPUT_A5, false);
    MAP_ADC14_configureConversionMemory(ADC_MEM6,
            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
            ADC_INPUT_A6, false);
    MAP_ADC14_configureConversionMemory(ADC_MEM7,
            ADC_VREFPOS_INTBUF_VREFNEG_VSS,
            ADC_INPUT_A7, false);

    /* Enabling the interrupt when a conversion on channel 7 (end of sequence)
     *  is complete and enabling conversions */
    MAP_ADC14_enableInterrupt(ADC_INT7);

    /* Enabling Interrupts */
    MAP_Interrupt_enableInterrupt(INT_ADC14);
    MAP_Interrupt_enableMaster();

    /* Setting up the sample timer to automatically step through the sequence
     * convert.
     */
    MAP_ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION);

    /* Triggering the start of the sample */
    MAP_ADC14_enableConversion();
    MAP_ADC14_toggleConversionTrigger();

    /* Going to sleep */
    while (1)
    {
        MAP_PCM_gotoLPM0();
    }
}

/* This interrupt is fired whenever a conversion is completed and placed in
 * ADC_MEM7. This signals the end of conversion and the results array is
 * grabbed and placed in resultsBuffer */
void ADC14_IRQHandler(void)
{
    uint64_t status;

    status = MAP_ADC14_getEnabledInterruptStatus();
    MAP_ADC14_clearInterruptFlag(status);

    if(status & ADC_INT7)
    {
        MAP_ADC14_getMultiSequenceResult(resultsBuffer);
    }

}

  • Just for clarity: This call fills in all 8 array elements, but on subsequent runs resultsBuffer[2]->[7] are always the same (improbable for an ADC).

    If one believes that the driverlib.c supplied by CCS matches that in the ROM, there appears to be an incrementation bug in ADC14_getMultiSequenceResult.

    It creates a pointer to ADC14MEM0 as a uint32_t *, but increments that pointer by 0x04 for each item. As a result, it fills in resultsBuffer[1] from ADC14MEM4, resultsBuffer[2] from ADC14MEM8 and so on. Since ADC14MEM8 and up haven't been stored by the ADC, they don't change from run to run (but they're usually non-zero, completing the illusion).

    The workaround would appear to be to not use this function and copy the results yourself. You can treat ADC14MEM0-7 as an array (this function does) and just copy successive 32 bit words into resultBuffer[]'s 16-bit words.

    To save everyone a trip, here is what CCS is telling me is in [ROM] driverlib.c (I removed some whitespace).

    void ADC14_getMultiSequenceResult(uint16_t* res)
    {
        uint32_t *startAddr, *curAddr;
        uint32_t ii;
        startAddr = (uint32_t*) _ctlRegs[(ADC14->rCTL1.r & ADC14CSTARTADD_M)      >> 16];
        curAddr = startAddr;
        for (ii = 0; ii < 32; ii++)
        {
            res[ii] = *(((uint16_t*) curAddr) + 0x40);
            if (BITBAND_PERI((*curAddr), ADC14EOS_OFS))
                break;
            if (curAddr == _ctlRegs[31])
                curAddr = (uint32_t*) _ctlRegs[0];
            else
                curAddr += 0x04;                 //  <-------------------------increment by 16
        }
    }

  • Thijs & Bruce,

    I can confirm that this is a bug and I'll file a ticket to get this fixed ASAP. 

    Here is a working working work-around for the ISR. 

    }

    /* This interrupt is fired whenever a conversion is completed and placed in
     * ADC_MEM7. This signals the end of conversion and the results array is
     * grabbed and placed in resultsBuffer */
    void ADC14_IRQHandler(void)
    {
        uint64_t status;
    
        status = MAP_ADC14_getEnabledInterruptStatus();
        MAP_ADC14_clearInterruptFlag(status);
    
        if(status & ADC_INT7)
        {
    //        MAP_ADC14_getMultiSequenceResult(resultsBuffer);
            resultsBuffer[0] = MAP_ADC14_getResult(ADC_MEM0);
            resultsBuffer[1] = MAP_ADC14_getResult(ADC_MEM1);
            resultsBuffer[2] = MAP_ADC14_getResult(ADC_MEM2);
            resultsBuffer[3] = MAP_ADC14_getResult(ADC_MEM3);
            resultsBuffer[4] = MAP_ADC14_getResult(ADC_MEM4);
            resultsBuffer[5] = MAP_ADC14_getResult(ADC_MEM5);
            resultsBuffer[6] = MAP_ADC14_getResult(ADC_MEM6);
            resultsBuffer[7] = MAP_ADC14_getResult(ADC_MEM7);
    
        }
    
    }

  • Hey Bruce,

    Thanks for the quick response. I have  rewrote the driver lib code and it works fine now thanks :)

  • Or you could do that too :) Bug filed, this will likely be fixed in the Q1 SDK release (March or so just as an FYI). Either way, glad you're moving forward!

**Attention** This is a public forum