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.

Using GPIO Pins as Wake Up Sources for LPDS or Hibernate

Other Parts Discussed in Thread: CC3200SDK, UNIFLASH, CC3200

Greetings,

I've been using the HIB and  sleep_deepsleep examples that the CC3200SDK 1.1.0 provides to figure out how to use GPIO pins as wakeup sources, with no luck.

The code I have so far is:

#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>

// Driverlib includes
#include "hw_types.h"
#include "interrupt.h"
#include "hw_ints.h"
#include "hw_apps_rcm.h"
#include "hw_common_reg.h"
#include "prcm.h"
#include "rom.h"
#include "rom_map.h"
#include "interrupt.h"
#include "hw_memmap.h"
#include "timer.h"
#include "wdt.h"
#include "utils.h"
#include "hw_common_reg.h"
#include "gpio.h"
#include "pin.h"


// Common interface includes
#include "timer_if.h"
#include "wdt_if.h"
#include "uart_if.h"

//Our includes & defines
#include "pin_mux_config.h"
#include "mav_system.h"


#if defined(ccs)
extern void (* const g_pfnVectors[])(void);
#endif
#if defined(ewarm)
extern uVectorEntry __vector_table;
#endif


/*
 * GLOBAL VARIABLES
 */
int alertFlag = 0;
int alertTimerFlag = 0;
int pulseFlag = 0;

/*
 * FUNCTION DECLARATIONS
 */
static void BoardInit(void);
void InterruptTestInit(void);
void GPIOA1BaseHandler();

void SayHi();
void SayBye();
void PerformPRCMDeepSleepGPIOWakeup();
void PerformPRCMHibGPIOWakeup();
void PerformPRCMLPDSGPIOWakeup();

/*
 * INTERRUPT SERVICE ROUTINES
 */
void GPIOA1BaseHandler(){
	unsigned long ulStatus;
	ulStatus = GPIOIntStatus(GPIOA1_BASE, true);
	GPIOIntClear(GPIOA1_BASE, ulStatus);

	if(ulStatus == PULSE_PIN){
		pulseFlag = 1;
		SayHi();
		printf("Interrupt occured\n");
	}
}




/*
 * FUNCTION IMPLEMENTATIONS
 */
void PerformPRCMDeepSleepGPIOWakeup()
{
	// Enable the Sleep Clock
	MAP_PRCMPeripheralClkEnable(PRCM_GPIOA1, PRCM_DSLP_MODE_CLK || PRCM_SLP_MODE_CLK);

	//Enable Interrupt right before sleeping
	InterruptTestInit();

	// Enter DEEPSLEEP...WaitForInterrupt ARM intrinsic
	printf("GPIO_DEEPSLEEP: Entering Deep Sleep\n");
	MAP_UtilsDelay(80000);
	PRCMDeepSleepEnter();

	// Exited DEEPSLEEP
	GPIOIntDisable(PULSE_BASE, PULSE_PIN);
	printf("GPIO_DEEPSLEEP: Exiting Deep Sleep\n");

	//Disable Sleep Clock
	MAP_PRCMPeripheralClkDisable(PRCM_GPIOA1, PRCM_DSLP_MODE_CLK || PRCM_SLP_MODE_CLK);
}

void PerformPRCMHibGPIOWakeup()
{

	MAP_PRCMHibernateIntervalSet(5*32*1024);
	MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_GPIO13);

	//This one is new, not used in timer example
	MAP_PRCMHibernateWakeUpGPIOSelect(PRCM_HIB_GPIO13, PRCM_HIB_RISE_EDGE);

	//Enable Interrupt right before sleeping
	InterruptTestInit();

	//Time to hibernate
	printf("GPIO_HIBERNATE: Entering Hibernate\n");
	UtilsDelay(80000);
	MAP_PRCMHibernateEnter();

	//Exited Hibernate
	GPIOIntDisable(PULSE_BASE, PULSE_PIN);
	printf("GPIO_HIBERNATE: Exiting Hibernate\n");
}

void PerformPRCMLPDSGPIOWakeup()
{

	MAP_PRCMLPDSIntervalSet(5*32*1024);
	MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_GPIO13);

	//This one is new, not used in timer example
	MAP_PRCMLPDSWakeUpGPIOSelect(PRCM_LPDS_GPIO13, PRCM_LPDS_RISE_EDGE);


	//Enable Interrupt right before sleeping
	InterruptTestInit();


	SayBye();
	//Time to hibernate
	printf("GPIO_LPDS: Entering LPDS\n");
	UtilsDelay(80000);
	MAP_PRCMLPDSEnter();

	// Exited LPDS
	GPIOIntDisable(PULSE_BASE, PULSE_PIN);
	printf("GPIO_LPDS: Exiting LPDS\n");
}


int main(void) {

	BoardInit();
	PinMuxConfig();
	//	TimerConfig();

	SayHi();

	//	PerformPRCMDeepSleepGPIOWakeup();
	//	PerformPRCMHibGPIOWakeup();
	PerformPRCMLPDSGPIOWakeup();

	while(pulseFlag==0);
	while(1){
		SayBye();
	}
}

static void BoardInit(void) {
	/* In case of TI-RTOS vector table is initialize by OS itself */
#ifndef USE_TIRTOS
	// Set vector table base
#if defined(ccs)
	MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
#endif
#if defined(ewarm)
	MAP_IntVTableBaseSet((unsigned long)&__vector_table);
#endif
#endif
	// Enable Processor
	MAP_IntMasterEnable();
	MAP_IntEnable(FAULT_SYSTICK);

	PRCMCC3200MCUInit();
}

void InterruptTestInit(void){
	unsigned long ulStatus;

	//Set interrupt mode for pins
	GPIOIntTypeSet(PULSE_BASE, PULSE_PIN, GPIO_RISING_EDGE);

	//Register the interrupts A1 port with a handler
	GPIOIntRegister(PULSE_BASE, GPIOA1BaseHandler);

	//Clear the interrupt status for A1
	ulStatus = GPIOIntStatus(PULSE_BASE, false);
	GPIOIntClear(PULSE_BASE, ulStatus);

	//Enable the interrupt
	GPIOIntEnable(PULSE_BASE, PULSE_PIN);
}


void SayHi()
{
	GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_1,GPIO_PIN_1);
	UtilsDelay(8000000);
	GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_1,0);
	UtilsDelay(8000000);
}
void SayBye()
{
	GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_1,GPIO_PIN_1);
	UtilsDelay(4000000);
	GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_1,0);
	UtilsDelay(4000000);
	GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_1,GPIO_PIN_1);
	UtilsDelay(4000000);
	GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_1,0);
	UtilsDelay(4000000);
}

Where PULSE_BASE and PULSE_PIN are defined in an external header as GPIOA1_BASE and GPIO_PIN_5 respectively (Pin 4, or GPIO13).

My intention is to wake the MCU up when pin 4 receives a rising edge. Eventually, I will use a circuit connected to the pin to send the signal, but for testing purposes, I am using SW3. I am flashing the program using Uniflash and the MCU is entering LPDS / Hibernate, but is not waking up upon pressing the button. Am I overlooking something? I will gladly provide more information if necessary.


Thanks in advance,

Luis Murphy

  • Hi Luis,


    Please refer idle_profile example from SDK to configure GPIO as wake up source.

    Also refer processors.wiki.ti.com/.../CC32xx_Summary_of_Known_Issues for a known issue related to setting GPIO as wakeup source on rising edge.


    Regards,
    Aashish
  • Hello Aashish,
    Thank you for the prompt reply, I will look into the example and the issue you pointed out and let you know if it leads me to the solution.

    Luis Murphy
  • Greetings,

    I applied driverlib changes 3 and 4 from the list of issues. After reading idle_profile, I understood that I had to call the SetGPIOAsWkUp function before entering LPDS or Hibernate.

    cc_hndl SetGPIOAsWkUp()
    {
        cc_hndl tGPIOHndl;
        //
        // setting up GPIO as a wk up source and configuring other related
        // parameters
        //
        tGPIOHndl = cc_gpio_open(GPIO_SRC_WKUP, GPIO_DIR_INPUT);
        cc_gpio_enable_notification(tGPIOHndl, GPIO_SRC_WKUP, INT_FALLING_EDGE,
                                    (GPIO_TYPE_NORMAL | GPIO_TYPE_WAKE_SOURCE));
        return(tGPIOHndl);
    }

    I pasted this function to the main I posted earlier and called it before calling PRCMLPDSEnter, but I still face the same issue, the CC3200 enters LPM but never turns back on.

  • Hi Luis,

    Some clarification regarding the low power modes.

    1. When the device wakes up from hibernate, it doesn't continue from the point where it entered the hibernate. Instead it starts execution from the main(like a restart).

    2. When the device enters LPDS, the RAM can be retained(by default). But the program counter, stack pointer and other registers are lost. You need to save them before entering LPDS and restore them after coming out of LPDS. Also you need to re-enable the clock for the peripherals used.

    3. For saving and restoration the program counter and stack pointer you need to call MAP_PRCMLPDSRestoreInfoSet(program_counter, stack_pointer) just before entering into LPDS(this will also take care of restoring them after coming out of LPDS). Make sure that the program counter should be point to the next instruction after MAP_PRCMLPDSEnter(). Also, stack pointer to be saved will depend if you are running your application in an OS environment or non-OS environment.
    /* In OS mode psp has to be saved*/
    /* In NON-OS mode msp has to be saved */

    4. Not every GPIO can wake up the system from low power modes. only Following GPIOs can be used to wake the system from LPDS or Hibernate:

    GPIO2
    GPIO4
    GPIO13
    GPIO17
    GPIO11
    GPIO24
    GPIO26

    CC3200SDK has a middleware library, which takes care of most of the above settings. Please refer to idle_profile(LPDS in OS env. ), sensor_profile(HIB in OS env.), idle_profile_nonos(LPDS in NON-OS env.).

    Can you try these examples once? let me know if you face any issues

    Thanks and Regards,
    Rahul