quasiyoke

STM32 L152 programming with libopencm3

In my last post I’ve described long way of configuring non-proprietary toolchain for ARM programming. I was pretty satisfied with it except two of its elements: Eclipse (I’m not a fan of large IDEs) and proprietary STM32 L1 standard peripheral library. The post have also covered cherry-picking of needed files from this libray to transform STM32 F1 blinking “hello world” to STM32 L1 blinking project. Today I’ve found much faster way to start STM32 L1 programming.

This article’s toolchain consist of:

  1. Any text editor (I prefer Sublime Text),
  2. GNU ARM Embedded toolchain,
  3. OpenOCD,
  4. Open source STLINK tool.

As you can see, I’ve used most of the parts from my last post. This toolchain will give you even more control and transparency on building process and of course it doesn’t have any proprietary software in it (except Sublime, but you’re able to use Atom or Vim).

You need some library to program your microcontroller (MCU) because usually you need to operate a plenty of sophisticated registers. All these registers usually have addresses like this: 0x40020C00. It’s better to operate with some human-readable code instead of all this digits, so you either need to define addresses as constants by yourself or use a library written by experienced developers. In my last post I used proprietary STM32 L1 standard peripheral library. Today I’m going to show you how to use GNU libopencm3 for that.

GNU ARM Embedded toolchain

I’m going to repeat installation steps from last article here to achieve completeness of this guide. So, usual APT commands for installing ARM cross-compilation tools (assuming you’re using some Debian-based distribution like Ubuntu):

sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa
sudo apt update
sudo apt install gcc-arm-none-eabi gdb-arm-none-eabi

If installation finished correctly you should be able to test toolchain’s version.

arm-none-eabi-gcc --version

OpenOCD

Setting up the tool for hardware debugging.

sudo apt install openocd
cd ~/Downloads/
git clone https://github.com/texane/stlink.git
cd ~/Downloads/stlink/
sudo install -m 644 etc/udev/rules.d/49-stlinkv2.rules /etc/udev/rules.d/49-stlinkv2.rules
sudo udevadm control --reload-rules

libopencm3 examples

libopencm3 is a GNU alternative for STM32 standard peripheral libraries. The project’s GitHub contains libopencm3 examples repository. If you clone this repo you’ll be able to build any example and flash it with simple terminal commands.

git clone https://github.com/libopencm3/libopencm3-examples.git
cd libopencm3-examples
git submodule init
git submodule update
make

When I did it, building have stopped with error at building examples/sam/d/d10-xplained-mini/miniblink/ stage (examples rev.: 9fbac7d, libopencm3 rev.: 13d4302). I don’t know what’s the reason of that but I don’t care about Atmel SAM. If you’ve got the same error ignore it, connect your STM32 L152 Discovery board through USB Mini-B cable and execute the following:

cd examples/stm32/l1/stm32l-discovery/miniblink
make flash

And that’s it! After that your board should start blinking with its LED.

LCD ticker

Let’s write some simple program using libopencm3 library. For example, LCD ticker.

The screen should display some text moving it forward rapidly.

LCD hello

At first I recommend you to write some trivial example to make sure all your tools are working right.

Let’s show some text at our screen. It’s already done at one of libopencm3 examples. This example just displays “*HELLO” string. I’ve copied it to my repo and adopted Makefile. The link is already pointing at the 1-lcd-hello tag.

To flash the program on your board just execute this:

git clone https://github.com/quasiyoke/stm32-l152-lcd-ticker.git
cd stm32-l152-lcd-ticker
git checkout 1-lcd-hello -- .
make flash

Find lcd_display_hello function inside main.c. This function determines the text we’re showing. Try to specify some other string. For example: “BYEBYE”

static void lcd_display_hello (void)
{
do {} while (!lcd_is_for_update_ready ());
clear_lcd_ram (); // all segments off
write_char_to_lcd_ram (0, 'B', true);
write_char_to_lcd_ram (1, 'Y', true);
write_char_to_lcd_ram (2, 'E', true);
write_char_to_lcd_ram (3, 'B', true);
write_char_to_lcd_ram (4, 'Y', true);
write_char_to_lcd_ram (5, 'E', true);

lcd_update ();
}

After your modifications, flash MCU again:

make flash

If you’ve broken something, don’t worry! Just checkout initial revision:

git checkout 1-lcd-hello -- .

Writing LCD ticker code

We’ll make LCD ticker in two steps:

  1. Writing function which shows arbitrary text
  2. Making the text move

Let’s make lcd_display_hello show any string from some specified position. I think this function should have another name since that: lcd_show. Look at the code:

/**
* Shows maximal possible part of the given text on LCD screen. If text is too
* short, shows it cycled.
* @param text Text to show
* @param offset Positive offset inside the text from which we should
* start showing it
*/
static void lcd_show(char* text, int offset)
{
const int TEXT_LENGTH = strlen(text);

do {} while (!lcd_is_for_update_ready());

for (int i=0; i<LCD_LETTERS_COUNT; ++i) {
write_char_to_lcd_ram(i, text[(offset + i) % TEXT_LENGTH], true);
}

lcd_update();
}

This function is called from main() with TEXT specified at main.h file.

You’re able to try this code by executing this:

git checkout 2-lcd-show -- .
make flash

Try to change offset specified at main function to see different parts of the string on the screen or shorten the string to less than 6 characters to see it repeated.

Moving text

To make text move let’s add infinite cycle to main():

int main(void)
{
const int TEXT_LENGTH = strlen(TEXT);

lcd_init();

for (int offset=0; ; ++offset, offset%=TEXT_LENGTH) {
lcd_show(TEXT, offset);

// Wait a bit
for (int i=0; i<100000; ++i) {
__asm__("nop");
}
}

return 0;
}

And this is the final program as you can see it in my repository.

To flash it do the following:

git checkout master
make flash