1
\$\begingroup\$

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?

\$\endgroup\$
  • \$\begingroup\$ Actually only PF0 needs to be unlocked in port F to be used as GPIO, that's why skipping unlock doesn't make a difference for PF4. \$\endgroup\$ – Roger C. Jan 5 '15 at 21:28
  • \$\begingroup\$ @RogerC. I'll have to double check the datasheet on those registers on this. Thnx for the pointer. \$\endgroup\$ – jippie Jan 5 '15 at 21:36
2
\$\begingroup\$

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

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.