LED blinks and serial echoes Dec 2016

Compiling software for the F103 is very easy but – as so often – does take a little preparation. In this case, we will need set up a few build files and make sure they are correct for the F103.

But first, let’s create a new directory and “chdir” into it:

mkdir ~/myf103apps
cd ~/myf103apps

Then you need these 3 files, which can all be downloaded from GitHub:

These files don’t have to be adjusted or changed in any way, they just need to be present.

Now we can finally create a first demo, and of course the first one to try is going to be the “Hello world” of Physical Computing: blinking the on-board LED - so let’s get moving!

Step 1 - Create a directory inside the one you just set up, called “blink”, and cd again:

mkdir blink
cd blink

Step 2 - Create a small, project-specific “Makefile”, with this contents:

BINARY = blink
LDSCRIPT = ../stm32f103.ld

default: $(BINARY).bin

include ../Makefile.include

Step 3 - Write the actual source code, in this case “blink.c”, with this contents:

#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>

int main (void) {
    gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
                    GPIO_CNF_OUTPUT_PUSHPULL, GPIO1);

    for (;;) {
        gpio_toggle(GPIOA, GPIO1);

        // create a small delay by looping for a while
        for (int i = 0; i < 1000000; ++i) __asm("");

Step 4 - Compile this new application by entering the following command:


Step 5 - Upload the generated blink.bin file to the Blue Pill:

This can be done as described in the previous article.

That’s it! - To make changes, simply edit blink.c and repeat steps 4 & 5.

Some notes:

Although it’s nice to see it working, a blinking LED isn’t going to keep you excited for long…

So let’s try something a little more complex: we periodically send out a message to the serial port, and when a <CR> (Carriage Return) character is received, we’ll toggle the on-board LED. In addition, we’ll write the code in C++ instead of C, and we’ll split up the code to use setup() and loop() functions, in the same way as the Arduino world is used to doing.

To reproduce this experiment, you need to make a copy of the “echo” area on GitHub.

The application-specific code is now in a file called “echo.cpp” (the rest is in “main.cpp”):

#include <libopencm3/stm32/gpio.h>
#include <stdio.h>

// defined in main.cpp
extern int serial_getc ();
extern uint32_t millis();

void setup () {
    // LED on HyTiny F103 is PA1, LED on BluePill F103 is PC13
    gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
                    GPIO_CNF_OUTPUT_PUSHPULL, GPIO1);
    gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
                    GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);

void loop () {
    printf("\nHit <enter> to toggle the LED (%lu) ...", millis());

    // the following loop takes roughly one second
    for (int i = 0; i < 1650000; ++i) {
        if (serial_getc() == '\r') {
            gpio_toggle(GPIOA, GPIO1);
            gpio_toggle(GPIOC, GPIO13);

Note the convenience of having a “grown-up” printf() at our disposal. This makes it very easy to generate good-looking text output on the serial port (it also increases the size of the generated application quite considerably, alas).

As before, you can enter make to build this, and then upload echo.bin to the Blue Pill (or HyTiny). Here is a sample session using Folie for uploading:

$ make
  CXX     main.cpp
  CXX     echo.cpp
  LD      echo.elf
  OBJCOPY echo.bin
   text	   data	    bss	    dec	    hex	filename
  28528	   2220	     64	  30812	   785c	echo.elf
$ folie -r
Select the serial port:
  1: /dev/cu.Bluetooth-Incoming-Port
  2: /dev/cu.usbmodem3430DC31
? 2
Enter '!help' for additional help, or ctrl-d to quit.
[connected to /dev/cu.usbmodem3430DC31]
!u echo.bin
  30748b +V22 #0410 R .W .E writing: 121/121 done.

Hit <enter> to toggle the LED (0) ...
Hit <enter> to toggle the LED (1008) ...
Hit <enter> to toggle the LED (2020) ...
Hit <enter> to toggle the LED (3032) ...

Note that Folie switches into terminal mode once the upload is complete, so the serial output immediately starts showing up. Hitting the Enter key toggles the LED, as expected. It works!

In case you’re wondering: while called “echo”, this example doesn’t really echo characters at all! It is left as an exercise for the reader to change the above example into one which does…

Weblog © Jean-Claude Wippler. Generated by Hugo.