Stellaris GPIO Data Direction Register Problem

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.

Reply to
EdV
Loading thread data ...

Did you remember to enable the clock for port G?

--

Tauno Voipio
Reply to
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++) { } } }

Reply to
EdV

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
Reply to
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

Reply to
EdV

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
Reply to
Tauno Voipio

Thanks!

Reply to
EdV

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
Reply to
Tim Wescott

  • 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
Reply to
Tim Wescott

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
Reply to
Tim Wescott

lock

. //

the

wer

he

OG)

Thanks!

Reply to
EdV

clock

ED. //

g the

).

nswer

the

r

PIOG)

Page 291 of

formatting link
makes it all clear.

Reply to
EdV

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.