Texas Instruments chips are renowned for their low power operations. In this example I will go through basics of the hibernate module available with Stellaris devices which enables the user to put the device i low power mode. This module becomes trivial in low power consumption demanding applications. They claim that the processor only consumes around 6 micro amperes of current when it is configured to work in the hibernate module. Within this article I will refer to the datasheet of the device where applicable.
It is fairly easy to use the hibernation module in the Stellaris devices through their “Peripheral driver library”. Also the module is very well explained in the datasheet. So I recommend everyone to go through the datasheet and understand the behavior of the module prior to coding. At-least, that is my approach. The hibernate module related information can be found in Chapter 7.
In this example I will use the external wake-up button to signal the processor to come out from the hibernation. If you go through the schematics of the launchpad, which is available at Page no 20 of launchpad user manual you will realize that the SW2 is connected to both the PF_0 and WAKE pin in the processor.
Once the processor is in the hibernation it can retain the GPIO states and some processor states too. When it comes out from the hibernation it acts as a Power ON reset. So you need to specifically handle the hibernate interrupts and carry out necessary configurations if you want to have a better control over the processes. Within this example that part will not be addressed. Please refer to section 7.3.10 in the datasheet for more information.
Moreover, here I will use the SW2 as a GPIO too. In order to configure the PF_0 as a GPIO pin you need to unlock that pin from NMI (non-maskable interrupt) mode. Refer to the section 10.2.4 in the datasheet. Following code will does exactly the same thing,
HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY_DD;
HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;
HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0;
Hibernation module can be configured using the following API calls,
SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
HibernateEnableExpClk(SysCtlClockGet());
HibernateWakeSet(HIBERNATE_WAKE_PIN);
HibernateGPIORetentionEnable();
The API calls are self explanatory. The processor will be put into the hibernation mode by executing the following API call.
HibernateRequest();
Here it will power off the microprocessor and will wait until a wake up condition occur.
In the following code, the user will first have to press SW1 to start the program. Then the Green LED will keep on blinking. Once both SW1 and SW2 were pressed the processor will go into the hibernation mode. Wake up pin can be accessed through SW2 to come out of hibernation.
Code:
/* * Hibernate example */
#include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "driverlib/timer.h" #include "driverlib/pin_map.h" #include "driverlib/hibernate.h"
void RedLEDBlink(); void BlueLEDBlink(); void GreenLEDBlink();
int main(void) { unsigned long a; // Configuring the clock to have 40 MHz SysCtlClockSet(SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ | SYSCTL_SYSDIV_5);
// Configure LEDs SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 , 0x00); RedLEDBlink();
// Unlock PF_0 HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY_DD; HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01; HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0; // Configure switches GPIOPinTypeGPIOInput(GPIO_PORTF_BASE,GPIO_PIN_0 | GPIO_PIN_4); GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
// Wait until SW1 is pressed while(GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4)); // Wait until SW1 is released while(!GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4)); RedLEDBlink();
// Configure hibernate module SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE); HibernateEnableExpClk(SysCtlClockGet()); HibernateWakeSet(HIBERNATE_WAKE_PIN);
while(1){ GreenLEDBlink();
// Check whether both SW1 and SW2 are pressed if(!GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4 | GPIO_PIN_0)) { // Loop until both SW1 and SW2 are released while(GPIOPinRead(GPIO_PORTF_BASE,GPIO_PIN_4 | GPIO_PIN_0) != 0x11); BlueLEDBlink(); HibernateGPIORetentionEnable(); HibernateRequest(); } } }
void RedLEDBlink() { GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1, 0xFF); SysCtlDelay(500000); GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1 , 0x00); SysCtlDelay(500000); }
void BlueLEDBlink() { GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_2, 0xFF); SysCtlDelay(500000); GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_2 , 0x00); SysCtlDelay(500000); }
void GreenLEDBlink() { GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3, 0xFF); SysCtlDelay(500000); GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3 , 0x00); SysCtlDelay(500000); }
In order to make this code work, you need to put all the include paths, linker paths and pre-processor definitions correctly. They can be found in the post related to ‘buttons.h’ in the blog.
Thank you.