I am trying to figure out how to properly use StellarisWare, the built in ROM calls, for GPIO. The Stellaris LaunchPad has two switches (SW1, SW2) and three LEDs (RED, GREEN, BLUE).
I wrote a little program that reads the switches and turns on the related LEDs when I push them. Everything works as expected:
- SW1 lights the green LED;
- SW2 lights the blue LED;
- SW1 & 2 simultaneously light the red LED.
This is the code:
#include "driverlib/gpio.c"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include <stdint.h>
#define LED_RED GPIO_PIN_1
#define LED_GREEN GPIO_PIN_3
#define LED_BLUE GPIO_PIN_2
#define SW1 GPIO_PIN_4
#define SW2 GPIO_PIN_0
#define GPIO_PORTF_LOCK_R (*((volatile unsigned long *)0x40025520))
#define GPIO_PORTF_CR_R (*((volatile unsigned long *)0x40025524))
#define GPIO_PORTF_DEN_R (*((volatile unsigned long *)0x4002551C))
int main() {
// Enable GPIO port
ROM_SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOF );
// Enable LED pins for output
ROM_GPIOPinTypeGPIOOutput( GPIO_PORTF_BASE , LED_RED | LED_GREEN | LED_BLUE );
// Enable switch pins for input
ROM_GPIOPinTypeGPIOInput( GPIO_PORTF_BASE , SW1 | SW2 );
// Enable switch pins pull up.
ROM_GPIOPadConfigSet( GPIO_PORTF_BASE , SW1 | SW2 , GPIO_STRENGTH_2MA , GPIO_PIN_TYPE_STD_WPU );
// GPIO Lock (GPIOLOCK)
GPIO_PORTF_LOCK_R = 0x4C4F434BU; // unlock the lock register
// GPIO Commit (GPIOCR)
GPIO_PORTF_CR_R = 0xFF; // enable commit for PORT F
// GPIO Digital Enable (GPIODEN)
GPIO_PORTF_DEN_R = 0xFFU; // enable digital on all pins in PORTF
while ( 1 ) {
switch( ROM_GPIOPinRead( GPIO_PORTF_BASE , SW1 | SW2 ) ^ ( SW1 | SW2 ) ) {
case SW1:
ROM_GPIOPinWrite( GPIO_PORTF_BASE , LED_RED | LED_GREEN | LED_BLUE , LED_GREEN );
break;
case SW2:
ROM_GPIOPinWrite( GPIO_PORTF_BASE , LED_RED | LED_GREEN | LED_BLUE , LED_BLUE );
break;
case SW1 | SW2:
ROM_GPIOPinWrite( GPIO_PORTF_BASE , LED_RED | LED_GREEN | LED_BLUE , LED_RED );
break;
default:
ROM_GPIOPinWrite( GPIO_PORTF_BASE , LED_RED | LED_GREEN | LED_BLUE , 0 );
break;
}
}
}
However, when I skip the six lines starting at // GPIO Lock (GPIOLOCK)
, the program starts to act in an unexpected way: SW2 is always read low, wheras SW1 is working as expected!
I would expect that there is a StellarisWare ROM call that does "the hard" stuff, but I can't seem to find the right call. So the question is: What (StellarisWare ROM call) am I overlooking here?
Best Answer
On most of the GPIO pins, there are more than one functions associated. On the pin having SW2, there is also an NMI (non-maskable interrupt) attached. This renders the pin to be unlocked first and then it can be used as a GPIO input.
As the comment suggests at line 6, you're basically unlocking SW2 pin to be used as a GPIO. All the pins having an alternate function of NMI are required to be unlocked first in order to be used.
For further details on NMI, you can refer to https://en.wikipedia.org/wiki/Non-maskable_interrupt