How to Program STMicro STM8S $1 Board in Linux

In January, I discovered there was such thing as a one dollar development board based on STMicro STM8S103F3P6 8-bit MCU with 1KB SRAM, 8KB flash, and 640 bytes EEPROM, some GPIOs as well as I2C, UART, SPI, ADC, and PWM signals. Links to documentation and source code were provided, but development tools were only Windows based. However, one of my reader informed me SDCC (Small Devices C Compiler) supported STM8, and development in Linux should be feasible. So I decided to buy the board on eBay for $1.62, as well as an ST_link V2 programmer for STM8 / STM32 for $4.52 in order to flash the firmware.

The board came pretty quickly, i.e. within 2 to 3 weeks.

STM8S103F3_BoardBut due to a lost package, the programmer took nearly 3 months to reach me, as the seller had to re-send after I failed to receive it within 2 months.

ST-Link_V2_ProgrammerIt comes with 4 wires that need to be connected to RST/NRST, 3.3V, SWIM, and GND. To do so, I had to solder a 4-pin header on the side of the board.

To get started with STM8 on Linux, I found some information on ColeVision website where they explained how to run Drystone on STM8/128-EVAL board using SDCC as the compiler, and stm8flash to program the board.

So I’ve given it a try on Ubuntu 14.04 with the simple goal of blinking the TEST LED on the board. sdcc is an Ubuntu package, so it’s pretty easy to install:

Let’s check the version and some more information:

sdcc --version
SDCC : mcs51/gbz80/z80/z180/r2k/r3ka/ds390/pic16/pic14/TININative/ds400/hc08/s08 3.3.0 #8604 (Dec 30 2013) (Linux)

That’s version 3.3.0 released in December 2013 and it lacks STM8 supports, but the latest version (sdcc v3.4.0) has been released in April 2014, and we can get it with a PPA, so let’s use that one instead:

If you are using Ubuntu 14.10 or greater, you’ll already get the latest version.

Let’s double check stm8 is indeed supported:

sdcc --version
SDCC : mcs51/z80/z180/r2k/r3ka/gbz80/tlcs90/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8 3.4.0 #8981 (Jan 10 2015) (Linux)
published under GNU General Public License (GPL)

Great! stm8 is now present in the list of supported MCUs.

For the next step was to install stm8flash tool to program the device:

Now I had to find some code samples to blink the LED. I started but checking the samples for ST Visual Programmer and IAR tools, combine with a modified version of Drystone source code, but I always had some issues with the header files, and it seems a bit more work than expected. But then I discovered that Valentin Dudouyt, stm8flash developer, also provided code samples in his github account, including a blinky sample:

First, I tried to compile the samples, and they failed because sp_test.c was missing, so I edited the Makefile to remove sp_test.ihx, and build was successful. The LED on the board is connected to B5 GPIO, so at that point I had to check out STM8S103F3 datasheet to find out more about the registers used in the sample. The register map is in section 6.2 of the document, and I need to use three registers:

  • PB_ODR – Port B data output latch register (Sets pin HIGH or LOW)
  • PB_DDR – Port B data direction register (Sets direction to INPUT or OUTPUT)
  • PB_CR1 – Port B control register 1

Since pin 5 correspond to 00100000 (0x20) I updated blinky.c sample as follows:

I typed make again to generate an updated firmware (blinky.ihx), and flash it as follows:

All good and the LED started blinking…

So now you should be able to write simple program to control other GPIOs, I2C, SPI, UART with the board. But if your program is a little more complex a debugger could be useful, and there’s Texane STLink working on Windows, Mac, and Linux, that can run gdbserver for STM32… But I tried it for STM8.

Then I ran st-link:

Hmmm, it does not look good, and sadly there’s no support for STM8 yet, as STM32 and STM8 use different interfaces (SWD vs SWIM).

So if you have troubles debugging your program, you may have to revert to Windows based tools, at least for now, unless you’re up for the task and want to add STM8 support to Texane.

Share this:
FacebookTwitterHacker NewsSlashdotRedditLinkedInPinterestFlipboardMeWeLineEmailShare

Support CNX Software! Donate via cryptocurrencies, become a Patron on Patreon, or purchase goods on Amazon or Aliexpress

ROCK Pi 4C Plus

31 Replies to “How to Program STMicro STM8S $1 Board in Linux”

  1. What is the USB port for? Reading the datasheet (quickly) seems to indicate that there is no USB device on that micro. Is it used for serial? If so, what’s doing the serial translation?

  2. Use openocd! Its so simple and so efficient!

    I actually used one of those stlink to flash a kinetis k10.

    There is a qstlink that is quite sweet as well.

  3. Great article. Just got my board and programmer in the mail, solder headers and I was good to go. Compiled a new version of sdcc on Linux Mint 13 and was able to compile your test program and flashed it. LED blinks! One question, how did you know B5 was hooked up to the LED? Do you have the schematic or did you just trace it with a multimeter? The docs on eBay points to a link where the documentation are all in Chinese. Thanks!

  4. There are also a few tutorials (led counter, UART, benchmarks) at, currently for two evaluation boards (STM8L-DISCOVERTY and STM8/128-EVAL); I hope I’ll find to get the versions for the other boards up sometime.


  5. Hello,

    Really nice tutorial! very helpfull for a starter/make everything works ok project.

    I have also verified that the LED is on pin B5 with a mutlimeter. but even if i change the registers in code my LED doesn’t flash.

    I am thinking that my board is dead, but writing with stm8flash seems to be done with no errors, i would expect that to not happen at all with a dead chip, right?

    Do you have any pointers on what i should check next? or maybe a different .c file that tests the chip functionallity?

    I did also check for a dead LED 🙂

  6. @Chris
    The LED test is one of the most basic test to check whether the board is working.

    I’d also assume you would not be able to flash a program is the board was dead.
    If you have a USB logic analyzer you could connect it to several GPIO to find if any other pin level is changed with your program. Maybe also check the datasheet if there’s some info about boot behavior, like a clock or something that you could check.

  7. @cnxsoft

    I tried to maybe connect a new LED on A2 Pin, next to ground.

    But the Datasheet is hard for my inexperienced eyes to read in order to decide what registers to use…

    Can you help me a bit on that? i also though of changing the problem a bit, and keep the B5 high all the time.
    Since i don’t own a logic analyzer ( yet ), maybe i can just keep it high and measure it with my mutlimeter?

    Thanks for the fast reply 🙂

  8. @Chris
    My LED also does not blink. Did you ever figure this out?
    Iv’e tested compiling and uploading with sdcc on Linux and Windows. Uploading works fine on both OS’s but the LED doesn’t blink.

    Iv’e ordered a couple more from Ebay and Ali-express just to make sure its not the board.

  9. @Andrew
    I have seen at least two different schematics for this board with the LED connected to different GPIO pins.
    So it’s possible your board is slightly different from mine.

    You could always check which GPIO pin is turned on/off with a multimeter, or have the program turn on and off all GPIOs to check your board is working.

  10. @cnxsoft
    Well I tested the LED and the red one is working but not the green one. So idk if thats the only problem or if there is more.
    I ordered 4 more from different places so I can confirm later when they arrive. Thanks for the tip.

  11. Because of the price I bought a STM8S board to. I’m started with discription on your website (and other websites too). In the first it was a good entry point, but I spend a lot of time to discover out, that the adresses declared in stm8l.h are different to the adresses for stm8s.

    This was find out by reading the reference manual. For the GPIO it doesn’t matter, but if you want to use the USART1, it won’t work for receiving datas.

    Another thing is the clock setup. In your example the STM8S the CPU is clocked by internal 2 MHz instead of internal 16 MHz because the adresses by example CLK_ICKR and CLK_PCKENR1 (and ohters too) are different.

    Buuuuuut : thanks for this site, this was my entry-point

    Nice regards,

  12. /* ———————————————–
    Registeradressen fuer einen STM8S MCU

    Originaldatei war fuer einen STM8L
    – geaenderte Registeradressen fuer CLK

    18.05.2016 R. Seelig
    ———————————————– */

    // GPIO
    #define PA_ODR *(unsigned char*)0x5000
    #define PA_IDR *(unsigned char*)0x5001
    #define PA_DDR *(unsigned char*)0x5002
    #define PA_CR1 *(unsigned char*)0x5003
    #define PA_CR2 *(unsigned char*)0x5004

    #define PB_ODR *(unsigned char*)0x5005
    #define PB_IDR *(unsigned char*)0x5006
    #define PB_DDR *(unsigned char*)0x5007
    #define PB_CR1 *(unsigned char*)0x5008
    #define PB_CR2 *(unsigned char*)0x5009

    #define PC_ODR *(unsigned char*)0x500A
    #define PC_IDR *(unsigned char*)0x500B
    #define PC_DDR *(unsigned char*)0x500C
    #define PC_CR1 *(unsigned char*)0x500D
    #define PC_CR2 *(unsigned char*)0x500E

    #define PD_ODR *(unsigned char*)0x500F
    #define PD_IDR *(unsigned char*)0x5010
    #define PD_DDR *(unsigned char*)0x5011
    #define PD_CR1 *(unsigned char*)0x5012
    #define PD_CR2 *(unsigned char*)0x5013

    #define PE_ODR *(unsigned char*)0x5014
    #define PE_IDR *(unsigned char*)0x5015
    #define PE_DDR *(unsigned char*)0x5016
    #define PE_CR1 *(unsigned char*)0x5017
    #define PE_CR2 *(unsigned char*)0x5018

    #define PF_ODR *(unsigned char*)0x5019
    #define PF_IDR *(unsigned char*)0x501A
    #define PF_DDR *(unsigned char*)0x501B
    #define PF_CR1 *(unsigned char*)0x501C
    #define PF_CR2 *(unsigned char*)0x501D

    // CLOCK : Bitadressen
    #define HSIEN (1 << 0)
    #define HSIRDY (1 << 1)
    #define SWEN (1 << 2)
    #define SWBSY (1 << 3)

    // CLOCK
    #define CLK_ICKR *(unsigned char*)0x50C0
    #define CLK_ECKR *(unsigned char*)0x50C1
    #define CLK_CMSR *(unsigned char*)0x50C3
    #define CLK_SWR *(unsigned char*)0x50C4
    #define CLK_SWCR *(unsigned char*)0x50C5
    #define CLK_CKDIVR *(unsigned char*)0x50C6
    #define CLK_PCKENR1 *(unsigned char*)0x50C7
    #define CLK_CSSR *(unsigned char*)0x50C8
    #define CLK_CCOR *(unsigned char*)0x50C9
    #define CLK_PCKENR2 *(unsigned char*)0x50CA
    #define CLK_HSITRIMR *(unsigned char*)0x50CC
    #define CLK_SWIMCCR *(unsigned char*)0x50CD

    // ——————- USART ——————-
    #define USART1_SR *(unsigned char*)0x5230
    #define USART1_DR *(unsigned char*)0x5231
    #define USART1_BRR1 *(unsigned char*)0x5232
    #define USART1_BRR2 *(unsigned char*)0x5233
    #define USART1_CR1 *(unsigned char*)0x5234
    #define USART1_CR2 *(unsigned char*)0x5235
    #define USART1_CR3 *(unsigned char*)0x5236
    #define USART1_CR4 *(unsigned char*)0x5237
    #define USART1_CR5 *(unsigned char*)0x5238
    #define USART1_GTR *(unsigned char*)0x5239
    #define USART1_PSCR *(unsigned char*)0x523A

    // USART_CR1 bits
    #define USART_CR1_R8 (1 << 7)
    #define USART_CR1_T8 (1 << 6)
    #define USART_CR1_UARTD (1 << 5)
    #define USART_CR1_M (1 << 4)
    #define USART_CR1_WAKE (1 << 3)
    #define USART_CR1_PCEN (1 << 2)
    #define USART_CR1_PS (1 << 1)
    #define USART_CR1_PIEN (1 << 0)

    // USART_CR2 bits
    #define USART_CR2_TIEN (1 << 7)
    #define USART_CR2_TCIEN (1 << 6)
    #define USART_CR2_RIEN (1 << 5)
    #define USART_CR2_ILIEN (1 << 4)
    #define USART_CR2_TEN (1 << 3)
    #define USART_CR2_REN (1 << 2)
    #define USART_CR2_RWU (1 << 1)
    #define USART_CR2_SBK (1 << 0)

    // USART_CR3 bits
    #define USART_CR3_LINEN (1 << 6)
    #define USART_CR3_STOP2 (1 << 5)
    #define USART_CR3_STOP1 (1 << 4)
    #define USART_CR3_CLKEN (1 << 3)
    #define USART_CR3_CPOL (1 << 2)
    #define USART_CR3_CPHA (1 << 1)
    #define USART_CR3_LBCL (1 << 0)

    // USART_SR bits
    #define USART_SR_TXE (1 << 7)
    #define USART_SR_TC (1 << 6)
    #define USART_SR_RXNE (1 << 5)
    #define USART_SR_IDLE (1 << 4)
    #define USART_SR_OR (1 << 3)
    #define USART_SR_NF (1 << 2)
    #define USART_SR_FE (1 << 1)
    #define USART_SR_PE (1 << 0)

    // ——————- TIMERS ——————-
    #define TIM1_CR1 *(unsigned char*)0x52B0
    #define TIM1_CR2 *(unsigned char*)0x52B1
    #define TIM1_SMCR *(unsigned char*)0x52B2
    #define TIM1_ETR *(unsigned char*)0x52B3
    #define TIM1_DER *(unsigned char*)0x52B4
    #define TIM1_IER *(unsigned char*)0x52B5
    #define TIM1_SR1 *(unsigned char*)0x52B6
    #define TIM1_SR2 *(unsigned char*)0x52B7
    #define TIM1_EGR *(unsigned char*)0x52B8
    #define TIM1_CCMR1 *(unsigned char*)0x52B9
    #define TIM1_CCMR2 *(unsigned char*)0x52BA
    #define TIM1_CCMR3 *(unsigned char*)0x52BB
    #define TIM1_CCMR4 *(unsigned char*)0x52BC
    #define TIM1_CCER1 *(unsigned char*)0x52BD
    #define TIM1_CCER2 *(unsigned char*)0x52BE
    #define TIM1_CNTRH *(unsigned char*)0x52BF
    #define TIM1_CNTRL *(unsigned char*)0x52C0
    #define TIM1_PSCRH *(unsigned char*)0x52C1
    #define TIM1_PSCRL *(unsigned char*)0x52C2
    #define TIM1_ARRH *(unsigned char*)0x52C3
    #define TIM1_ARRL *(unsigned char*)0x52C4
    #define TIM1_RCR *(unsigned char*)0x52C5
    #define TIM1_CCR1H *(unsigned char*)0x52C6
    #define TIM1_CCR1L *(unsigned char*)0x52C7
    #define TIM1_CCR2H *(unsigned char*)0x52C8
    #define TIM1_CCR2L *(unsigned char*)0x52C9
    #define TIM1_CCR3H *(unsigned char*)0x52CA
    #define TIM1_CCR3L *(unsigned char*)0x52CB
    #define TIM1_CCR4H *(unsigned char*)0x52CC
    #define TIM1_CCR4L *(unsigned char*)0x52CD
    #define TIM1_BKR *(unsigned char*)0x52CE
    #define TIM1_DTR *(unsigned char*)0x52CF
    #define TIM1_OISR *(unsigned char*)0x52D0
    #define TIM1_DCR1 *(unsigned char*)0x52D1
    #define TIM1_DCR2 *(unsigned char*)0x52D2
    #define TIM1_DMA1R *(unsigned char*)0x52D3

    // TIM_IER bits
    #define TIM_IER_BIE (1 << 7)
    #define TIM_IER_TIE (1 << 6)
    #define TIM_IER_COMIE (1 << 5)
    #define TIM_IER_CC4IE (1 << 4)
    #define TIM_IER_CC3IE (1 << 3)
    #define TIM_IER_CC2IE (1 << 2)
    #define TIM_IER_CC1IE (1 << 1)
    #define TIM_IER_UIE (1 << 0)

    // TIM_CR1 bits
    #define TIM_CR1_APRE (1 << 7)
    #define TIM_CR1_CMSH (1 << 6)
    #define TIM_CR1_CMSL (1 << 5)
    #define TIM_CR1_DIR (1 << 4)
    #define TIM_CR1_OPM (1 << 3)
    #define TIM_CR1_URS (1 << 2)
    #define TIM_CR1_UDIS (1 << 1)
    #define TIM_CR1_CEN (1 << 0)

    // TIM_SR1 bits
    #define TIM_SR1_BIF (1 << 7)
    #define TIM_SR1_TIF (1 << 6)
    #define TIM_SR1_COMIF (1 << 5)
    #define TIM_SR1_CC4IF (1 << 4)
    #define TIM_SR1_CC3IF (1 << 3)
    #define TIM_SR1_CC2IF (1 << 2)
    #define TIM_SR1_CC1IF (1 << 1)
    #define TIM_SR1_UIF (1 << 0)

    // Portbits

    #define PA0 0
    #define PA1 1
    #define PA2 2
    #define PA3 3
    #define PA4 4
    #define PA5 5
    #define PA6 6
    #define PA7 7

    #define PB0 0
    #define PB1 1
    #define PB2 2
    #define PB3 3
    #define PB4 4
    #define PB5 5
    #define PB6 6
    #define PB7 7

    #define PC0 0
    #define PC1 1
    #define PC2 2
    #define PC3 3
    #define PC4 4
    #define PC5 5
    #define PC6 6
    #define PC7 7

    #define PD0 0
    #define PD1 1
    #define PD2 2
    #define PD3 3
    #define PD4 4
    #define PD5 5
    #define PD6 6
    #define PD7 7

  13. Hello! When I try to install stm8flash in lubuntu 16.10 LTS. In the terminal appears this error after typing ‘make’:
    cc -g -O0 –std=gnu99 –pedantic pkg-config --cflags libusb-1.0 -c -o stlink.o stlink.c
    Package libusb-1.0 was not found in the pkg-config search path.
    Perhaps you should add the directory containing `libusb-1.0.pc’
    to the PKG_CONFIG_PATH environment variable
    No package ‘libusb-1.0’ found
    In file included from stlink.c:14:0:
    pgm.h:6:21: fatal error: libusb.h: No existe el archivo o el directorio
    compilation terminated.
    : fallo en las instrucciones para el objetivo ‘stlink.o’
    make: *** [stlink.o] Error 1

    Someone who can help me! Thank you!

  14. @zoobab

    I’ve never heard of versaloon, but looking at that page, it makes me think about the Black Magic Probe. ( ). The firmware can also be flashed to the cheap ST-Link clones as in the picture in the article. However, there is no STM8 support, only ARM support. GDB directly connects to the Black Magic Probe, without the need of OpenOCD. However, even though GDB itself seems to work fine with BMP, I haven’t gotten eclipse to work with it yet.

  15. I tried on Windows and success
    – got sdcc and stm8flash and libusb-1.0.dll from
    – add sduino-windowstools-master\tools\bin to %PATH%
    – install stlink driver (
    – my module is locked, so
    >stm8flash.exe -c stlinkv2 -p stm8s103f3 -s opt -w optdefault.bin.txt
    – got that blinky.c and stm8l.h
    >sdcc.exe -lstm8 -mstm8 –out-fmt-ihx blinky.c
    >stm8flash.exe -c stlinkv2 -p stm8s103f3 -w blinky.ihx

Leave a Reply

Your email address will not be published. Required fields are marked *

Khadas VIM4 SBC
Khadas VIM4 SBC