Cortex M0 GPIO hardfault

When working on a Cortex M0+ board bring-up the other day, I kept running into a hardfault as soon as I tried to write to the GPIO subsystem. The C code looked like this:

    // enable clocks to GPIO
    SIM_SCGC5 = SIM_SCGC5_PORTA | SIM_SCGC5_PORTB |
                SIM_SCGC5_PORTC | SIM_SCGC5_PORTD |
                SIM_SCGC5_PORTE | SIM_SCGC5_LPTIMER;
    
    // set PIN E18 as output
    PORTE_PCR18 = 0x0100; // set MUX to digital out
    PORTE_PDDR = 0x40000; // 18

The exception was triggered by “PORTE_PCR18 = 0x0100;” and it took me a while to figure out was was going on.

The Cortex processors will throw a hardfault exception when writing to peripherals that don’t have their clock enabled. But I enabled the clock — or so I thought..

Like all RISC processors, commands issued by the core can take a few clock cycles to arrive at the peripherals, depending on the depth of the pipeline. Then there is the latency of the peripheral itself. In the case above, the clocks to the GPIO subsystem haven’t been enabled before the processor executes the write to PORT E and a hardfault is triggered.

The solution is to do something else between writing to SIM_SCGC5 and PORTE, or insert NOPs, like this:

    // enable clocks to GPIO
    SIM_SCGC5 = SIM_SCGC5_PORTA | SIM_SCGC5_PORTB |
                SIM_SCGC5_PORTC | SIM_SCGC5_PORTD |
                SIM_SCGC5_PORTE | SIM_SCGC5_LPTIMER;

    asm volatile ("nop");
    asm volatile ("nop");    

    // set PIN E18 as output
    PORTE_PCR18 = 0x0100; // set MUX to digital out
    PORTE_PDDR = 0x40000; // 18

No more hardfaults!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s