Computing stuff tied to the physical world

Minimal code, the basics

The power of µC’s is their immense flexibility, because they are completely controlled through software, most often nowdays in the form of program written in C or C++.

If you’re familiar with Arduino’s (or JeeNodes), then brace yourself: we’ll be going a lot deeper here, and we’re going to set up our own “runtime startup code”. We’re going to completely take control of the µC from the microsecond it starts up. The benefits are a deeper understanding and a much lower code overhead, the main drawback is that it will take somewhat more effort to get there than downloading the Arduino IDE and firing it up.

But no worries. Here too, our minimalist starting point will pay off nicely: we only need to set up a few things to get our blinking LED going.

So, here’s the circuit again, now stripped to its bare essentials. How can we make it blink?

Lpc810pwr

There’s something odd going on here, and it’s very much on purpose: the LED is inserted in series with the µC, while the whole thing is powered from the FTDI’s 5V supply pin. As you may remember, that’s more than the maximum allowed for an LPC810 chip, but here’s the trick: a red LED tends to have a forward voltage drop of about 1.7V, i.e. when conducting. So with 1.7V less, the µC is in fact getting power as it should: with a supply voltage of ≈ 3.3V (anything between 1.8 and 3.6 V is fine for the LPC810). Note that the LED’s primary role here is not to light up, but to act as a basic voltage reducing component!

Anyway, the challenge is to make that LED blink. And the solution is a bit unusual: we’re going to make the µC consume more or less power. While drawing current, the LED will be on. When asleep, the LED will be off. By modulating power use, we can control the LED.

So the goal is to make the LED blink, but the task of the code will be to power up and put the LPC810 into an ultra low-power sleep mode. If we can do this periodically, we’re home.

Lets do it:

#include "LPC8xx.h"

int main () {
    LPC_SYSCON->SYSAHBCLKCTRL |= 1<<9;  // SYSCTL_CLOCK_WKT
    LPC_PMU->DPDCTRL |= (1<<2)|(1<<3);  // LPOSCEN and LPOSCDPDEN
    LPC_WKT->CTRL = 1<<0;               // WKT_CTRL_CLKSEL

    NVIC_EnableIRQ(WKT_IRQn);

    LPC_SYSCON->STARTERP1 = 1<<15;      // wake up from alarm/wake timer
    SCB->SCR |= 1<<2;                   // enable SLEEPDEEP mode
    LPC_PMU->PCON = 3;                  // enter deep power-down mode

    for (int count = 0; count < 900000; ++count)
        __ASM("");                      // waste time while drawing current

    LPC_WKT->COUNT = 5000;              // 10 KHz / 5000 -> wakeup in 500 ms
    __WFI();                            // wait for interrupt, powers down

    // waking up from deep power-down leads to a full reset, no need to loop
    while (true) ;                      // yak shaving: 4 bytes less ;)
}

extern "C" void WKT_IRQHandler () {
    LPC_WKT->CTRL = LPC_WKT->CTRL;      // clear the alarm interrupt
}

The first point to make about this code is that you’re not expected to read through this and nod in complete agreement and understanding. There’s really a lot going on here, and it’s happening at a frightfully primitive chip level. Lines such as LPC_PMU->PCON = 3; are a way to directly manipulate the hardware of the LPC810 chip in C. And the documentation for all this is buried in a 370-page datasheet (PDF: UM10601) – all for a tiny 8-pin µC chip.

Some notes about the above code, to give you an idea of what’s going on:

  • lines 7..15 are required to prepare the chip for ultra low-power sleeping
  • lines 17..18 spend 0.5 seconds doing “nothing” to keep the LED on
  • lines 20..21 set up a 0.5 s watchdog timeout and enter “deep power down” mode
  • line 24 is never reached, because the µC resets itself when it wakes up again
  • lines 27..29 define a wake-up time interrupt handler which clears the interrupt

That’s not the whole story. You’re looking at the main() code, but there’s another 180-line C file which is essential to make the µC call our main code. Not to mention 5 header files with 3,000 lines of definitions from ARM and NXP, as needed for all this.

If you’re curious, it’s all on the web for you to look at. This example and everything needed to build and upload it is in a new GitHub repository from JeeLabs called embello. The files for this minimal example can be found in this directory.

There are two steps missing to actually make our LED blink: (cross-) compiling the above software and uploading the resulting binary file into into our LPC810 chip. We can skip the compile step for now, because the compiler output file is also on GitHub as “firmware.bin”.

We just need to figure out how to load our carefully crafted code into the chip.

[Back to article index]