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.

MSPM0G3507: MEMRESIFG bit not cleared as expected

Part Number: MSPM0G3507

Hello,

I've had issues with the ADC getting the status of a conversion finished. I was reading the MEMRESIFG bits from the CPU_INT.RIS register for the channels I care about, to know when a conversion on a channel finished, via DL_ADC12_getRawInterruptStatus(). Then I would read the result of the conversion with DL_ADC12_getMemResult(), which according to the TRM should clear the MEMRESIFG bit. However this does not happen. Bit remains set and next conversion gives me an invalid value because MEMRESIFG is already set when starting next conversion, so my SW ends it prematurely.

I looked at adc12_single_conversion SDK example which works correctly, because it uses DL_ADC12_getPendingInterrupt() and not DL_ADC12_getRawInterruptStatus(), so it seems the bit is cleared as soon as IIDX register is read. However I cannot use that in my application since it won't always give me the status of the exact channel that I want depending on the state of the system. I modified the SDK example to use DL_ADC12_getRawInterruptStatus() instead, and sure enough, the MEMRESIFG bit is never cleared when reading the converison result register.

See below the modified SDK example to reproduce this:

/*
 * Copyright (c) 2020, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "ti_msp_dl_config.h"

volatile bool gCheckADC;
volatile uint16_t gAdcResult;

int main(void)
{
    SYSCFG_DL_init();

    NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
    gCheckADC = false;

    while (1) {
        DL_ADC12_startConversion(ADC12_0_INST);

        while (false == gCheckADC) {
            __WFE();
        }

        gAdcResult = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);

        if (gAdcResult > 0x7ff) {
            DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
        } else {
            DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
        }
        gCheckADC = false;
        DL_ADC12_enableConversions(ADC12_0_INST);
    }
}

void ADC12_0_INST_IRQHandler(void)
{
    switch (DL_ADC12_getRawInterruptStatus(ADC12_0_INST, DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED)) {
        case DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED:
            gCheckADC = true;
            break;
        default:
            break;
    }
}

Can you please confirm if you see this behavior on TI side?

Thank you,

Florin

  • Hi Florin,

    The raw interrupt status will have every interrupt that gets captured on that peripheral. I recommend using the get pending interrupt function because it will pull from the masked interrupts.

    If you insist on the raw interrupt status you will need to use a different value instead of DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED. DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED is set to 0x9 whereas the RIS has mem0 result interrupt status mask is 0x100;

    In your ISR you will need to clear the interrupt status manually.

    #include "ti_msp_dl_config.h"
    
    volatile bool gCheckADC;
    volatile uint16_t gAdcResult;
    
    int main(void)
    {
        SYSCFG_DL_init();
    
        NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
        gCheckADC = false;
    
        while (1) {
            DL_ADC12_startConversion(ADC12_0_INST);
    
            while (false == gCheckADC) {
                __WFE();
            }
    
            gAdcResult = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);
    
            if (gAdcResult > 0x7ff) {
                DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
            } else {
                DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
            }
            gCheckADC = false;
            DL_ADC12_enableConversions(ADC12_0_INST);
        }
    }
    
    void ADC12_0_INST_IRQHandler(void)
    {
        uint32_t val = DL_ADC12_getRawInterruptStatus(ADC12_0_INST, 0x100);
        switch (val) {
            case 0x100:
                DL_ADC12_clearInterruptStatus(ADC12_0_INST, 0x100);
                gCheckADC = true;
                break;
            default:
                break;
        }
    }

    I do see in the TRM that it states reading the result register should be clearing the corresponding interrupt bits, but it looks like that is not the case. I will investigate as to what the appropriate procedure is and we will update our documentation accordingly.

    Regards,
    Luke

  • Hello Luke,

    Our application uses the raw interrupt status because we are not using interrupts on ADC but polling.

    DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED is actually redirecting to ADC12_CPU_INT_IMASK_MEMRESIFG0_SET, so it's the correct value to use in this case.

    Anyway thank you for confirming the issue with those ADC bits. Can you please write an update here once you are able to tell which document will be updated for this? Errata or TRM I presume

    Best regards,

    Florin

  • Hi Florin,

    I will update once it is decided which document will be updated.

    Regards,

    Luke