PDA

View Full Version : Getting started with raw C: GPIO initialization?



spacewrench
11-30-2012, 06:47 AM
Does anybody know how to use the Teensy3 in raw C mode (not using the Arduino stuff)? I have my compiler set up, and I'm using the mk20dx128.{c,h,ld} from the Arduino Teensy directory, but with the following code in my main():


PORTC_PCR5 = (0b001 << 8) | (1 << 6);
GPIOC_PDIR = (1 << 5); // Port C5 = output
GPIOC_PDOR = 0;

for ( ; ; ) {
GPIOC_PTOR = (1 << 5);
for (unsigned i = 0; i < 5000000; ++i) asm( "nop" );
}

I think this should blink the LED, but it doesn't, so I'd guess I'm not enabling digital mode or output or GPIO clock or something. (GPIO clock is actually set in the mk20dx128.c startup code, but anyway...)

cmason
11-30-2012, 08:01 PM
Do you maybe mean GPIOC_PDDR = 1 << 5;

You perhaps know this, but the teensy3 directory will pretty much compile on its own without any of the "arduino stuff" save the compiler. I don't use the Arduino IDE (I'm using AppCode) and I just have a copy of the teensy3 directory in version control (https://bitbucket.org/cmason/teensy3/src/tip/teensy).

I understand the desire to work at a low level, but having Paul's code (for instance pinMode(13, OUTPUT); digitalWrite(13, HIGH); ) even just as a reference is pretty useful. :)

I'm finding like you are that it's seems always necessary to set some other twiddly bit distal to the peripheral you're using. Like I wasted hours yesterday getting bus errors before I discovered you have to enable clock to the DMA MUX (but not the DMA controller itself -- weird). Never mentioned in the relevant DMA chapters, but only in the SIM chapter.

Best,

-c

PaulStoffregen
11-30-2012, 08:10 PM
Are you using the ResetHandler() function? If not, you need at least this to enable the GPIO clocks:

SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO

Also, the watchdog is active by default after a reset, and by default it has a very short timeout. The first thing you could should do is disable the watchdog, or program it the way you want. The watchdog also has a feature where it becomes unchangeable after a certain number of clock cycles, so you can't reconfigure it later.

The default ResetHandler does this to disable the watchdog.

WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE;

spacewrench
12-01-2012, 03:51 AM
> Do you maybe mean GPIOC_PDDR = 1 << 5;

Yes, yes I do. (I made the exact same mistake years ago with a Philips ARM processor. Why, oh why, do they have a DDR and a DIR?)

> Are you using the ResetHandler() function?

Yes, although I commented out the SysTick stuff and the __enable_irq() (wasn't sure what sort of interrupts the Arduino uses!)

Unfortunately, still not working. I'm sure it's something obvious & stupid. Am I doing the right thing with PORTC_PCR5?

spacewrench
12-02-2012, 01:55 AM
Man, I hate complicated init code (that I didn't write myself!) I ended up commenting out everything I didn't understand in ResetHandler, and I now have a blinking LED. Woo hoo. Not sure what was keeping me from getting to main(), but also not much inclined to investigate. I have USB host code to write!

PaulStoffregen
12-02-2012, 03:04 AM
If you commented out all that clock setup stuff, then you're probably running at approx 29 MHz based on the internal oscillator.

For USB to work, the PLL must be running at a multiple of 24 MHz, and the USB prescaler set to generate a 48 MHz clock for the USB.