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.

CCS/MSP432P401R: Toggle GPIO

Part Number: MSP432P401R

Tool/software: Code Composer Studio

Hi,

I´m having some issues developing a low power application with MSP432 Launchpad. The idea is to keep the micro under LPM3, wake it up every minute to power on some sensor, delay with systick, measure, power off sensors and finally go back to sleep. It´s not much of a thing and got it up working nicely.

While I´m using CCS8 debug mode everything works fine. But then when I reboot my launchpad and try to measure power consumption with EnergyTrace things start to fail. Sensor power pins never go low again.

I´ve changed a little bit my code so instead of using sensors now, I´m just waking up from LPM3 every minute, turn on a led on pin 5.2, delay with sysTick and powering off the led. The led only turns off while using debug mode... I´ve tried using both MAP_GPIO_setOutputLowOnPin and P5OUT ^= 0x04; I´m completly lost at this point.

 

void main(void)
{
    // ULP MODE
	WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;		// stop watchdog timer
    PADIR = 0xFFFF;
    PBDIR = 0xFFFF;
    PCDIR = 0xFFFF;
    PDDIR = 0xFFFF;
    PEDIR = 0xFFFF;
    PJDIR = 0xFFFF;
    PAOUT = 0;
    PBOUT = 0;
    PCOUT = 0;
    PDOUT = 0;
    PEOUT = 0;
    PJOUT = 0;
    MAP_SysCtl_enableSRAMBankRetention(SYSCTL_SRAM_BANK1);

    // Downgrade Frequency to 12 MHz
    CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);

    /* el modo ULP pone todos los pines a 0. Eso hace que los canales I2C consuman. Hay que crear funciones para los sensores que activen y desactiven estos puertos... */

    ADS1220_init();

    // debug
    int epoch = 1552733990;
    TIME_startRTC(epoch);

    /* bucle infinito. Mantiene el micro en estado de ultra bajo consumo */
    while (1)
    {
        MAP_Interrupt_enableSleepOnIsrExit();
        MAP_Interrupt_enableMaster();
        __enable_interrupt();
        __low_power_mode_3();
    }
}


void activateSystick(int delay)
{
    // Configuring SysTick to trigger at 6.000.000 is 1 second
    MAP_SysTick_enableModule();
    MAP_SysTick_setPeriod(delay);
    MAP_Interrupt_enableSleepOnIsrExit();
    MAP_SysTick_enableInterrupt();
}


void activate_sensors(void)
{
    GPIO_setOutputHighOnPin(ADS1220_POWER_PORT, ADS1220_POWER_PIN);  // pin 5.2

    //ADS1220_beginPTR();

    stateMeasure = true;
    activateSystick(1500000);
}

void shutdown_sensors(void)
{
    //ADS1220_shutDown();
    P5OUT ^= 0x04;
    //MAP_GPIO_setOutputLowOnPin(ADS1220_POWER_PORT, ADS1220_POWER_PIN);  // pin 5.2

}

void measure_sensors(void)
{
    int hora = 0;

    hora = TIME_secondsSinceEpoch();

    shutdown_sensors();
}


void SysTick_Handler(void)
{
    MAP_SysTick_disableModule();
    if (stateMeasure)
    {
        stateMeasure = false;
        measure_sensors();
    }
}


/*******************************************************************************
 * RTC ISR
 * Atiende las interrupciones generadas por:
 *******************************************************************************/
void RTC_C_IRQHandler(void)
{
    uint32_t status;
    status = MAP_RTC_C_getEnabledInterruptStatus();
    MAP_RTC_C_clearInterruptFlag(status);

    if (status & RTC_C_TIME_EVENT_INTERRUPT) {
        activate_sensors();
    }
}

Would really apreciate some help here.

  • I forgot to say, function ADS1220_init() (called on main) enables port 5.2 as output:

    void ADS1220_init(void){
        /* SPI */
        MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(SPI_PORT_B2, SPI_CLK_PIN_B2 | SPI_MOSI_PIN_B2, GPIO_PRIMARY_MODULE_FUNCTION);
        GPIO_setAsPeripheralModuleFunctionInputPin(SPI_PORT_B2, SPI_MISO_PIN_B2, GPIO_PRIMARY_MODULE_FUNCTION);
        SPI_initMaster(EUSCI_B2_BASE, &spiMasterConfig);
        SPI_enableModule(EUSCI_B2_BASE);
        SPI_disableModule(EUSCI_B2_BASE);
    
        MAP_GPIO_setAsOutputPin(ADS1220_POWER_PORT, ADS1220_POWER_PIN);
        MAP_GPIO_setAsOutputPin(ADS1220_CS_PORT, ADS1220_CS_PIN);
    }

  • I am confused about the relationship between the debugger and the issue you are describing. If your code is/was working, then please go back to the working state and simply connect the 3V rail and disconnect all other IO related to JTAG and the backchannel UART and measure the current with energy trace.

    e2e.ti.com/.../2755877

    Regards,
    Chris
  • Right now I´m just connecting a led between pins 5.2 and ground.

    My script only turns off pin 5.2 while using CCS8 on debug. If I connect my lunchpad to a batterry or any other power source pin 5.2 will stay high for ever... Once the first RTC alarms is triggered the led emits light. But it never stops.
  • The only thing I can think of is that the debugger will prevent the device from actually entering LPM3. I would recommend checking out an LPM3 example and comparing with how the LPM3 is handled.

    dev.ti.com/.../

    Regards,
    Chris
  • Chris,

    I´ve managed to solve the problem. Instead of using SysTick interruptions I´ve changed it to use Timer32 instead. Now the led changes works as expected.

    The code remains the same. Just changed 'activateSystick(int delay)' call function with an 'activateTimer32(int delay)' following 'timer32_periodic_mode_led_toggle.c' example. Kind of rare things work with one interruption but not the other.

    Tomorrow morning I´ll check the code with the sensors and let you know how things are going. Luckily we can close this threat.

    Thanks for all your responses.
  • Thanks for the feedback. Yes that makes sense since the SysTick is running from MCLK. When a transition to deepSleep (lpm3) is requested this will be rejected if there is a clock request that is not supported in deepSleep mode unless the clock request logic is disabled or the rude mode is enabled. It does not make sense that Timer32 would work because the peripheral is still requesting the same clock. I will keep looking.

    Are you using an RTOS or a scheduler that is configuring Systick?

    Chris
  • Chris,

    Sorry I din´t reply you yesterday. Had a long day...

    I tested the code with some of the sensors (ADS120 and SHT35) and all worked fine.

    I´m not using RTOS. Just pure C. My idea is to handle the MSP432 as state machine. 

    My MSP432 is always in LPM3 and wakes up with interruptions. The idea is to wake up the board every minute (RTC interrupt) and measure. To reduce power I only turn on sensors just before measuring. I tried using systick between turning on sensors and measuring so they had time to 'heat' themselves. As told you before It only worked using timer32 instead.

    I still have one doubt regarding MCLK. In my code I´m using MSP432 internal RTC, Timer32, SPI and I2C. And I´m also reducing central frequency to 12 MHz. I´m not sure about RTC, but all the others use MCLK. Can this produce some conflict? Can this somehow end up with errors in the RTC (not given the correct date-time)?

  • Thank you for the additional information.  The RTC can only use the system BCLK which can be sourced from either the internal REFOCLK or the external LFXTCLK.   The MCLK is a separate system clock, so there is no conflict or interaction.  MCLK will go away in LPM3 while the REFOCLK or LFXTCLK (whichever is used for the RTC) will remain on.  In addition to the 1 minute interrupt you are also taking a time stamp from the RTC?  

    Do  you use the 'rude mode' before entering LPM3?

        MAP_PCM_enableRudeMode();

    Thanks,

    Chris

  • Hello,
    Is there any further questions for this thread?

    Regards,
    Chris
  • Chris,

    Yes, I´m tacking a timestamp when ever the RTC interrupt goes on.The idea is to measure the sensors and knowing the datetime they´ve been taken.

    I´m not using

    MAP_PCM_enableRudeMode();

    If I did, how would it affect the RTC? The code I´m using to start the RTC is:TC is:

    void TIME_startRTC(int epoch)
    {
        RTC_C_Calendar currentTime = TIME_epochToTime(epoch);
    
        /* Configuring pins for peripheral/crystal usage and LED for output */
        MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ, GPIO_PIN0 | GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);
    
        /* Setting the external clock frequency. This API is optional, but will
         * come in handy if the user ever wants to use the getMCLK/getACLK/etc
         * functions
         */
        CS_setExternalClockSourceFrequency(32000,12000000);
    
        /* Starting LFXT in non-bypass mode without a timeout. */
        CS_startLFXT(CS_LFXT_DRIVE3);
    
        /* Initializing RTC with current time as described in time in definitions section */
        MAP_RTC_C_initCalendar(&currentTime, RTC_C_FORMAT_BINARY);
    
        /* Specify an interrupt to assert every minute */
        MAP_RTC_C_setCalendarEvent(RTC_C_CALENDAREVENT_MINUTECHANGE);
    
        /* Enable interrupt for RTC Ready Status, which asserts when the RTC
         * Calendar registers are ready to read.
         * Also, enable interrupts for the Calendar alarm and Calendar event. */
        MAP_RTC_C_clearInterruptFlag(RTC_C_TIME_EVENT_INTERRUPT);
        MAP_RTC_C_enableInterrupt(RTC_C_TIME_EVENT_INTERRUPT);
    
        /* Start RTC Clock */
        MAP_RTC_C_startClock();
    
        /* Enable interrupts and go to sleep. */
        MAP_Interrupt_enableInterrupt(INT_RTC_C);
    }





  • The rude mode will not impact the RTC, but will ensure that a request to enter deepsleep (LPM3) is granted.

    Regards,
    Chris
  • Any updates on this issue?

    Thanks,
    Chris
  • Chris,

    Everything is working fine now. Thank you so much for you´re help.

**Attention** This is a public forum