Stellaris GPIO Data Direction Register Problem

Sep 14, 2011 11 Replies

So, I am trying to extend a "Blinky" (blinks an LED) example program that came with the IAR Kickstart IDE and debugger. When I initialize more than one data direction register the code runs but the signals no longer "output."



Any thoughts?



The code below toggles PH7 if I uncomment "//GPIO_PORTG_DIR_R =



0x03;" no more I/O output.

main(void) { volatile unsigned long ulLoop;



// // Enable the GPIO port that is used for the on-board LED. // //SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOA; //SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF; SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOG; SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOH;



// // Do a dummy read to insert a few cycles after enabling the peripheral. // ulLoop = SYSCTL_RCGC2_R;



// // Enable the GPIO pin for the LED (PF3). Set the direction as output, and // enable the GPIO pin for digital function. // PX0 use 0x01, PX1 use 0x02, PX2 use 0x04, PX3 use 0x08, // Px4 use 0x10, PX5 use 0x20, PX6 use 0x40, PX7 use 0x80 //GPIO_PORTA_DIR_R = 0x08; //GPIO_PORTF_DIR_R = 0x01; //GPIO_PORTG_DIR_R = 0x03; GPIO_PORTH_DIR_R = 0x80;



//GPIO_PORTA_DEN_R = 0x08; //GPIO_PORTF_DEN_R = 0x01; //GPIO_PORTG_DEN_R = 0x03; GPIO_PORTH_DEN_R = 0x80;



while(1) { // // Turn on the LED. // //GPIO_PORTA_DATA_R |= 0x08; //GPIO_PORTF_DATA_R |= 0x01; //GPIO_PORTG_DATA_R |= 0x03; GPIO_PORTH_DATA_R |= 0x80;



// // Delay for a bit. // for(ulLoop = 0; ulLoop < 400000; ulLoop++) { }



// // Turn off the LED. // //GPIO_PORTA_DATA_R &= ~(0x08); //GPIO_PORTF_DATA_R &= ~(0x01); //GPIO_PORTG_DATA_R &= ~(0x03); GPIO_PORTH_DATA_R &= ~(0x80);



// // Delay for a bit. // for(ulLoop = 0; ulLoop < 100000; ulLoop++) } Note this is a code snippet and the "{" and "}" are not necessarily in the right place.



Thanks much!



Ed V.


Did you remember to enable the clock for port G?

Tauno Voipio

on as

Hi, thanks for the advice. I am not seeing where there is a clock involved in "blinky" though. Below is the "main" for the example.

//

***************************************************************************= ** // // Blink the on-board LED. // // ***************************************************************************= ** int main(void) { volatile unsigned long ulLoop;

// // Enable the GPIO port that is used for the on-board LED. // SYSCTL_RCGC2_R =3D SYSCTL_RCGC2_GPIOF; // Do a dummy read to insert a few cycles after enabling the peripheral. // ulLoop =3D SYSCTL_RCGC2_R;

// // Enable the GPIO pin for the LED (PF3). Set the direction as output, and // enable the GPIO pin for digital function. // GPIO_PORTF_DIR_R =3D 0x18; GPIO_PORTF_DEN_R =3D 0x18; GPIO_PORTE_DIR_R =3D 0x0F; GPIO_PORTE_DEN_R =3D 0x0F;

// // Loop forever. // while(1) { // // Turn on the LED. // GPIO_PORTF_DATA_R |=3D 0x18; GPIO_PORTE_DATA_R |=3D 0x0F; // // Delay for a bit. // for(ulLoop =3D 0; ulLoop < 2000000; ulLoop++) { }

// // Turn off the LED. // GPIO_PORTF_DATA_R &=3D ~(0x18); GPIO_PORTE_DATA_R &=3D ~(0x0F);

// // Delay for a bit. // for(ulLoop =3D 0; ulLoop < 2000000; ulLoop++) { } } }

Here:*******************^^^^^^^^^^^^^^^^^^

Please re-read the chip documentation (a couple of hundreds of pages).

My experience is from LM3S6965 and LM3S818, but all the Stellaris Cortexes are pretty similar.

Tauno Voipio

k

I tried adding the dummy read after peripheral enable in several instances and it does not make a difference. I think I found the answer although I don't really understand it:

SYSCTL_RCGC2_R =3D SYSCTL_RCGC2_GPIOG + SYSCTL_RCGC2_GPIOH; Concatenating(I think) of SYSCTL_RCGC2_R is required rather than

this-- SYSCTL_RCGC2_R =3D SYSCTL_RCGC2_GPIOG; SYSCTL_RCGC2_R =3D SYSCTL_RCGC2_GPIOH;

Thanks much for getting me looking. I actually found this googling the data sheet didn't have it. Maybe the GPIO specific manual?

Best, Ed

Hello Ed,

If you do it like this:

you'll disable GPIO G with the second write.

You should use instead:

Please get the datasheet and read from System Control / Register Descriptions / Run Mode Clock Gating Control 2.

The first write can also be an or into the control register.

Tauno Voipio

That's IT!!! I hadn't said anything because I looked and looked and looked and didn't see the problem. But now I see it.

He did set the clock -- in this line:

SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOG;

but that line is immediately followed by this one:

SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOH;

Ed: You're trying to set _bit_. When you set

SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOG;

you're setting all of the bits in the SYSCTL register to equal the bit pattern in SYSCTL_RCGC2_GPIOG. Then you go and set them all to equal SYSCTL_RCGC2_GPIOH -- which turns the clock off to GPIOG. Then, when you try to write to GPIOG, the processor does a hardware fault interrupt.

You want to do one of two things: The way that's parsimonious with clock ticks is to collect all your writes to bits in SYSCTL into one:

SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOG | SYSCTL_RCGC2_GPIOH;

The way that's much, much safer is to or in the bits you want to set:

SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOG; SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOH;

I _always_ do this -- that way if I follow up with some other code that executes earlier that sets some bits, I don't stomp on things.

www.wescottdesign.com

  • Always do an 'or equal (bit pattern)' to set such bits.
  • Always do an 'and equal ~(bit pattern)' to reset such bits.
  • Always set necessary bits in an init function in the code where you use the bits -- even if you end up setting the same bits a dozen times (I do this for GPIO pins whose use is scattered around)

You'll save yourself a lot of grief.

www.wescottdesign.com

You want to use a bitwise OR.

Consider a large system where you're doing a bunch of different stuff, possibly with bit definitions is different header files. Now consider the two defines:

#define ALL_THE_BITS_BOB_NEEDS SYSCTL_RCGC2_GPIOG #define ALL_THE_BITS_MARY_NEEDS (SYSCTL_RCGC2_GPIOA | SYSCTL_RCGC2_GPIOG)

_Now_ consider the difference between the following two lines of code:

This:

SYSCTL_RCGC2_R = ALL_THE_BITS_BOB_NEEDS + ALL_THE_BITS_MARY_NEEDS;

vs. this:

SYSCTL_RCGC2_R = ALL_THE_BITS_BOB_NEEDS | ALL_THE_BITS_MARY_NEEDS;

www.wescottdesign.com

lock

. //

the

wer

he

OG)

Thanks!

clock

ED. //

g the

).

nswer

the

r

PIOG)

Page 291 of

formatting link
makes it all clear.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required