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.

MSPM0L1306-Q1: Programming after shutdown mode requires Factory Reset

Part Number: MSPM0L1306-Q1
Other Parts Discussed in Thread: MSPM0L1306

Hello,

I'm working on a custom board, which requires the uC to go to shutdown mode, wake up from external source, do stuff with ADC and PWM, then go back to shutdown mode. So far so good, it works fine.

But, whenever I try to reconnect to the uC using XDS programmes, I receive the error message “Error connecting to the target: (Error -614 @ 0x0) The target indicates there is an error condition from a previous SWD request. Clear the error the condition, and try the SWD request again. (Emulation package 9.12.0.00150)”, so I have to restart the uC in BSL mode (powewr up with PA18 up), then send the factoryReset command from CCS, power cycle again and reprogram the board. Every single time!

I implemented my code as depicted in the sysctl_shutdown example included in the SDK package, I ran it on the LP_MSPM0L1306 demo board without issues, I double checked the two configurations, but I did'nt see anything significative.

Below you can find my main function and my syscfg configuration file

/**
 * These arguments were used when this file was generated. They will be automatically applied on subsequent loads
 * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
 * @cliArgs --device "MSPM0L130X" --package "VSSOP-20(DGS20)" --part "Default" --product "mspm0_sdk@1.20.00.05"
 * @versions {"tool":"1.18.0+3266"}
 */

/**
 * Import the modules used in this configuration.
 */
const ADC12  = scripting.addModule("/ti/driverlib/ADC12", {}, false);
const ADC121 = ADC12.addInstance();
const Board  = scripting.addModule("/ti/driverlib/Board");
const GPIO   = scripting.addModule("/ti/driverlib/GPIO", {}, false);
const GPIO1  = GPIO.addInstance();
const PWM    = scripting.addModule("/ti/driverlib/PWM", {}, false);
const PWM1   = PWM.addInstance();
const SYSCTL = scripting.addModule("/ti/driverlib/SYSCTL");
const TIMER  = scripting.addModule("/ti/driverlib/TIMER", {}, false);
const TIMER1 = TIMER.addInstance();
const TIMER2 = TIMER.addInstance();
const UART   = scripting.addModule("/ti/driverlib/UART", {}, false);
const UART1  = UART.addInstance();

/**
 * Write custom configuration values to the imported modules.
 */
const gate6  = system.clockTree["MFCLKGATE"];
gate6.enable = true;

const oscillator2           = system.clockTree["SYSOSC"];
oscillator2.frequencySelect = 4;

ADC121.$name                      = "ADC12_0";
ADC121.adcMem1chansel             = "DL_ADC12_INPUT_CHAN_1";
ADC121.adcMem2chansel             = "DL_ADC12_INPUT_CHAN_2";
ADC121.adcMem3chansel             = "DL_ADC12_INPUT_CHAN_3";
ADC121.adcMem0_name               = "AI_VBAT_MON";
ADC121.adcMem1_name               = "AI_MOTOR_P";
ADC121.adcMem2_name               = "AI_MOTOR_N";
ADC121.adcMem3_name               = "AI_MOTOR_I";
ADC121.endAdd                     = 3;
ADC121.sampleMode                 = "DL_ADC12_SAMPLING_SOURCE_MANUAL";
ADC121.interruptPriority          = "2";
ADC121.adcMem0avgen               = true;
ADC121.hwNumerator                = "DL_ADC12_HW_AVG_NUM_ACC_8";
ADC121.hwDenominator              = "DL_ADC12_HW_AVG_DEN_DIV_BY_8";
ADC121.peripheral.$assign         = "ADC0";
ADC121.peripheral.adcPin0.$assign = "PA27";
ADC121.adcPin0Config.$name        = "ti_driverlib_gpio_GPIOPinGeneric0";

Board.genPeriphPinFile   = true;
Board.peripheral.$assign = "DEBUGSS";
Board.genFileMod.$name   = "ti_driverlib_BoardPins0";

GPIO1.$name                               = "GPIO_GRP_0";
GPIO1.associatedPins.create(6);
GPIO1.associatedPins[0].$name             = "DO_MOTOR_DIR";
GPIO1.associatedPins[0].pin.$assign       = "PA6";
GPIO1.associatedPins[1].$name             = "DO_MOTOR_EN";
GPIO1.associatedPins[1].pin.$assign       = "PA22";
GPIO1.associatedPins[2].$name             = "DI_ST_MOTOR";
GPIO1.associatedPins[2].direction         = "INPUT";
GPIO1.associatedPins[2].pin.$assign       = "PA2";
GPIO1.associatedPins[3].$name             = "DI_SW_BWD";
GPIO1.associatedPins[3].direction         = "INPUT";
GPIO1.associatedPins[3].interruptPriority = "1";
GPIO1.associatedPins[3].interruptEn       = true;
GPIO1.associatedPins[3].polarity          = "RISE";
GPIO1.associatedPins[3].ioStructure       = "OD";
GPIO1.associatedPins[3].pin.$assign       = "PA0";
GPIO1.associatedPins[4].$name             = "VBAT_SW_EN";
GPIO1.associatedPins[4].pin.$assign       = "PA4";
GPIO1.associatedPins[5].$name             = "VBAT_MON_EN";
GPIO1.associatedPins[5].pin.$assign       = "PA23";

PWM1.$name                              = "DO_PWM_MOTOR";
PWM1.clockSource                        = "MFCLK";
PWM1.timerCount                         = 200;
PWM1.ccIndex                            = [0];
PWM1.peripheral.$assign                 = "TIMG0";
PWM1.peripheral.ccp0Pin.$assign         = "PA16";
PWM1.PWM_CHANNEL_0.$name                = "ti_driverlib_pwm_PWMTimerCC0";
PWM1.ccp0PinConfig.direction            = scripting.forceWrite("OUTPUT");
PWM1.ccp0PinConfig.hideOutputInversion  = scripting.forceWrite(false);
PWM1.ccp0PinConfig.onlyInternalResistor = scripting.forceWrite(false);
PWM1.ccp0PinConfig.passedPeripheralType = scripting.forceWrite("Digital");
PWM1.ccp0PinConfig.$name                = "ti_driverlib_gpio_GPIOPinGeneric3";

SYSCTL.clockTreeEn = true;
SYSCTL.powerPolicy = "STANDBY0";

TIMER1.$name              = "TIMER_WAIT";
TIMER1.timerClkSrc        = "MFCLK";
TIMER1.timerClkDiv        = 8;
TIMER1.timerClkPrescale   = 50;
TIMER1.timerPeriod        = "300 ms";
TIMER1.peripheral.$assign = "TIMG2";

TIMER2.interrupts         = ["ZERO"];
TIMER2.timerClkSrc        = "LFCLK";
TIMER2.$name              = "TIMER_WAKE_UP";
TIMER2.timerPeriod        = "99 ms";
TIMER2.peripheral.$assign = "TIMG1";

UART1.$name                    = "UART_0";
UART1.targetBaudRate           = 115200;
UART1.enabledInterrupts        = ["RX","RXD_NEG_EDGE","RXD_POS_EDGE"];
UART1.uartClkSrc               = "MFCLK";
UART1.peripheral.$assign       = "UART0";
UART1.peripheral.rxPin.$assign = "PA18";
UART1.peripheral.txPin.$assign = "PA17/OPA1.IN0-";
UART1.txPinConfig.$name        = "ti_driverlib_gpio_GPIOPinGeneric1";
UART1.rxPinConfig.$name        = "ti_driverlib_gpio_GPIOPinGeneric2";

/**
 * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
 * version of the tool will not impact the pinmux you originally saw.  These lines can be completely deleted in order to
 * re-solve from scratch.
 */
Board.peripheral.swclkPin.$suggestSolution = "PA20";
Board.peripheral.swdioPin.$suggestSolution = "PA19";
/*
 * Copyright (c) 2021, 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 <string.h>
#include <stdio.h>
#include <ti/driverlib/dl_adc12.h>
#include <ti/driverlib/dl_gpio.h>
#include <ti/driverlib/dl_timerg.h>
#include <ti/driverlib/dl_uart_main.h>
#include <ti_msp_dl_config.h>


 
void uart_log(char* str, const uint8_t len)
{
    for(uint8_t i=0; i< len; ++i)
    {
        DL_UART_Main_transmitDataBlocking(UART_0_INST,str[i]);
    }
}

void print_value_u32(const uint8_t id, const uint32_t v)
{
    const char formatValue[] = "value %i: %i\r\n";
    char output[50] = {0};

    sprintf(output,formatValue,id,v);
    uart_log(output,strlen(output));
}

void GROUP1_IRQHandler()
{

}

void UART_0_INST_IRQHandler()
{


}

void TIMER_WAKE_UP_INST_IRQHandler()
{

}


int main(void)
{
    volatile uint16_t lAiVbatMon =   0u;
    volatile uint32_t lVbat =        0u;
    
    volatile DL_SYSCTL_RESET_CAUSE resetCause;

    SYSCFG_DL_init();  

    resetCause = DL_SYSCTL_getResetCause();

    if(resetCause == DL_SYSCTL_RESET_CAUSE_BOR_WAKE_FROM_SHUTDOWN)
    {
        
        SYSCFG_DL_GPIO_init();
        DL_SYSCTL_releaseShutdownIO();
        DL_GPIO_disableWakeUp(GPIO_GRP_0_DI_SW_BWD_IOMUX);
        DL_GPIO_disableWakeUp(GPIO_GRP_0_DI_ST_MOTOR_IOMUX);
        DL_GPIO_disableWakeUp(GPIO_GRP_0_DO_MOTOR_DIR_IOMUX);
        DL_GPIO_disableWakeUp(GPIO_GRP_0_DO_MOTOR_EN_IOMUX);
        DL_GPIO_disableWakeUp(GPIO_GRP_0_VBAT_MON_EN_IOMUX);
        DL_GPIO_disableWakeUp(GPIO_GRP_0_VBAT_SW_EN_IOMUX);
        DL_GPIO_disableWakeUp(GPIO_UART_0_IOMUX_RX);
        DL_GPIO_disableWakeUp(GPIO_UART_0_IOMUX_TX);
        DL_GPIO_disableWakeUp(GPIO_DO_PWM_MOTOR_C0_IOMUX);

    }  

    // DL_GPIO_setPins(GPIO_GRP_0_PORT,GPIO_GRP_0_VBAT_SW_EN_PIN);
    

    /* turn off peripherals before going to standby0 mode */
    DL_ADC12_disablePower(ADC12_0_INST);
    DL_UART_Main_disablePower(UART_0_INST);
    DL_TimerG_disablePower(DO_PWM_MOTOR_INST);
    DL_TimerG_disablePower(TIMER_WAIT_INST);
    DL_SYSCTL_setPowerPolicySHUTDOWN();

    

    // NVIC_EnableIRQ(GPIO_GRP_0_INT_IRQN);
    // NVIC_EnableIRQ(UART_0_INST_INT_IRQN);
    // NVIC_EnableIRQ(TIMER_WAKE_UP_INST_INT_IRQN);

    // DL_GPIO_enableFastWakePins(GPIO_GRP_0_PORT,GPIO_GRP_0_DI_SW_BWD_PIN);

    // char startupstr[100] = {0};
    // char name[] = "BMW Emergency Box";
    // char version[] = "v0.1";
    // sprintf(startupstr,"%s - %s (%X) (%X) (%X) - (reset: %X)\r\n",name,version,FACTORYREGION->DEVICEID,FACTORYREGION->USERID,FACTORYREGION->TRACEID, resetCause);
    // uart_log(startupstr,strlen(startupstr));   


    

    DL_GPIO_setPins(GPIO_GRP_0_PORT,GPIO_GRP_0_DO_MOTOR_DIR_PIN);

    static volatile uint32_t lIsSwitchActivated = 0u;
    lIsSwitchActivated = DL_GPIO_readPins(GPIO_GRP_0_PORT,GPIO_GRP_0_DI_SW_BWD_PIN);

    /* check on input switch */
    if((lIsSwitchActivated & GPIO_GRP_0_DI_SW_BWD_PIN) != GPIO_GRP_0_DI_SW_BWD_PIN)
    {
        /* switch has been activated! */

        /* power on ADC */
        DL_ADC12_enablePower(ADC12_0_INST);
        DL_UART_Main_enablePower(UART_0_INST);

        /* enable ADC conversion */
        DL_ADC12_enableConversions(ADC12_0_INST);

        /* enable Vbat monitor */
        DL_GPIO_setPins(GPIO_GRP_0_PORT,GPIO_GRP_0_VBAT_MON_EN_PIN);

        /* wait 0.5 ms, to wait load of capacitance on input pin to be read by ADC*/
        DL_Common_delayCycles(2000u);

        /* start adc sampling */
        DL_ADC12_startConversion(ADC12_0_INST);

        /* wait 50 cycles sampling */
        DL_Common_delayCycles(50u);

        /* stop adc sampling and start conversion */
        DL_ADC12_stopConversion(ADC12_0_INST);

        /* wait end of conversion */
        while(DL_ADC12_isConversionsEnabled(ADC12_0_INST) == true);

        /* read adc values */
        lAiVbatMon = DL_ADC12_getMemResult(ADC12_0_INST,ADC12_0_ADCMEM_AI_VBAT_MON);
        // print_value_u32(0u,lAiVbatMon);

        /* turn off ADC and UART */
        DL_ADC12_disablePower(ADC12_0_INST);
        DL_UART_disablePower(UART_0_INST);

        /* disable Vbat monitor */
        DL_GPIO_clearPins(GPIO_GRP_0_PORT,GPIO_GRP_0_VBAT_MON_EN_PIN);

        /* calc Vbat (mV) */
        /* 
            Vbat = (Vcc/2^ADCResolution) * ADCrawValue * VoltageDividerFactor
            Vcc = 3.3 V (3300 mV)
            ADCResolution = 12 bits
            VoltageDividerFactor = 8
        */
        lVbat = (3300u * lAiVbatMon * 8u) / (4096u);
        // print_value_u32(1u,lVbat);

        /* check against threshold: if Vbat is above 9V, activate motor */
        if(lVbat > 9000u)
        {
            /* motor must be activated! */

            /* enable PWM timer */
            DL_TimerG_enablePower(DO_PWM_MOTOR_INST);

            /* enable wait timer */
            DL_TimerG_enablePower(TIMER_WAIT_INST);

            /* enable motor driver */
            DL_GPIO_setPins(GPIO_GRP_0_PORT,GPIO_GRP_0_DO_MOTOR_EN_PIN);

            /* drive motor with 100% PWM */
            DL_TimerG_setCaptureCompareValue(DO_PWM_MOTOR_INST,150,GPIO_DO_PWM_MOTOR_C0_IDX);
            DL_TimerG_startCounter(DO_PWM_MOTOR_INST);

            /* wait 300 ms before stoppin the motor */
            DL_TimerG_startCounter(TIMER_WAIT_INST);
            while(DL_TimerG_isRunning(TIMER_WAIT_INST) == true);

            /* stop motor */
            DL_TimerG_stopCounter(DO_PWM_MOTOR_INST);

            /* disable motor driver */
            DL_GPIO_clearPins(GPIO_GRP_0_PORT,GPIO_GRP_0_DO_MOTOR_EN_PIN);

            /* disable PWM timer*/
            DL_TimerG_disablePower(DO_PWM_MOTOR_INST);

            /* disable wait timer */
            DL_TimerG_disablePower(TIMER_WAIT_INST);


        } /*  end of if(Vbat > 9000u) */
    } /* end of if((lIsSwitchActivated & GPIO_GRP_0_DI_SW_BWD_PIN) == 0u) */

    DL_GPIO_initDigitalInputFeatures(GPIO_GRP_0_DI_SW_BWD_IOMUX,DL_GPIO_INVERSION_DISABLE,DL_GPIO_RESISTOR_NONE,DL_GPIO_HYSTERESIS_DISABLE,DL_GPIO_WAKEUP_ON_1);
    DL_Common_delayCycles(4000u);
    DL_GPIO_clearPins(GPIO_GRP_0_PORT,GPIO_GRP_0_DO_MOTOR_DIR_PIN);
    

    while(1)
    {
        __WFI();
    }
}

Regards,

Daniele

  • Hi Daniele,

    Maybe you can add some delay before device enter the shutdown mode:

            delay_cycles(16000000);

    Such as the example code will have some delay:

    B.R.

    Sal

  • Yeah, it works, thank you!

    I misunderstood the technical reference manual (or maybe an incoherence is present), slau847c: at paragraph 2.1.2.5 the document states that the device can be waken up by an IO, an NRST or a debug connection, then in a note at paragraph 2.4.7 the document states that also debug oins remain locked when exiting shutdown operating mode.

    I suggest to better clarify this behavior in the document.

    Thank you again for support!