Skip to content

Instantly share code, notes, and snippets.

@stecman
Last active January 2, 2023 18:33
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stecman/bb2c61db0fd21ae8dee9e4b4264c5a51 to your computer and use it in GitHub Desktop.
Save stecman/bb2c61db0fd21ae8dee9e4b4264c5a51 to your computer and use it in GitHub Desktop.
SCons build script for STM8 / STM8S with SDCC

SCons + SDCC for STM8S

Setting up SCons to build using SDCC was fairly time consuming for someone new to SCons, so here's a basic working config to get you started.

With some tweaking this should also work for other architectures that SDCC supports (z80, z180, mcs51, r2k, etc).

Required software

SCons (build tool)

This should be available in your distribution's pacakage manager. It can also be installed via Python's pip package manager.

SDCC (compiler)

SDCC may be available in your distro's package manager. I recommend installing from source to get the most recent release, as the Debian and Ubuntu repos can be a few versions behind:

# Download release or snapshot from:
# - https://sourceforge.net/projects/sdcc/files/sdcc/
# - http://sdcc.sourceforge.net/snap.php

# or with SVN
svn co http://svn.code.sf.net/p/sdcc/code/trunk sdcc

cd sdcc/sdcc
./configure
make
sudo make install

stm8flash (flashing tool)

stm8flash uses an STLink V1/V2 to program STM8 devices through their SWIM interface.

This needs to be compiled from source currently, which is simple:

git clone https://github.com/vdudouyt/stm8flash
cd stm8flash
make
sudo make install

STM8 Standard Peripheral Library for SDCC

I've released a modified version of STM8S/A driver from ST that supports SDCC. The code available from ST Micro doesn't support SDCC out of the box.

cd your-project
git clone https://github.com/stecman/stm8s-sdcc.git driver

A similar project also exists here.

Usage

  • Install all of the software above
  • Copy both of the files below into a directory:
wget https://gist.githubusercontent.com/stecman/bb2c61db0fd21ae8dee9e4b4264c5a51/raw/SConscript \
     https://gist.githubusercontent.com/stecman/bb2c61db0fd21ae8dee9e4b4264c5a51/raw/SConstruct
  • Run scons to build your hex file, or scons flash to build and flash

Blinky example

#include "stm8s.h"

// Calculate a timer overflow value
// This is found by (BLINK_SECONDS / (1/(CLOCK_SPEED_MHZ/PRESCALER)))
#define OVERFLOW 31250L

// Mask for the pin to flash
#define LED_PIN (1<<5)

int main()
{
    // Configure the clock for maximum speed on the 16MHz HSI oscillator
    // At startup the clock output is divided by 8
    CLK->CKDIVR = 0x0;

    // Confirgure B5 in fast push-pull mode
    // On some STM8 dev boards, this is connected to an LED
    GPIOB->DDR |= LED_PIN;
    GPIOB->CR1 |= LED_PIN;
    GPIOB->ODR |= LED_PIN;

    // Configure timer 2 (16-bit general purpose) to count to 500ms
    TIM2->PSCR = TIM2_PRESCALER_256;

    // Set "auto-reload" value (the timer counts from zero to this number)
    // When this number is reached, the TIM2 overflow interrupt is triggered
    TIM2->ARRH = OVERFLOW >> 8;
    TIM2->ARRL = OVERFLOW;

    // Enable interrupt
    TIM2->IER = TIM2_IER_UIE;

    // Enable counter (start counting)
    TIM2->CR1 = TIM2_CR1_CEN;

    enableInterrupts();

    for (;;) {
        // Do nothing so we don't halt
    }
}

void timer2_overflow_interrupt(void) __interrupt (ITC_IRQ_TIM2_OVF)
{
    // Toggle pin
    GPIOB->ODR ^= LED_PIN;

    // Clear the timer overflow so the interrupt doesn't fire again immediately
    TIM2->SR1 &= ~TIM2_SR1_UIF;
}
# Device definition for the stm8s.h header
# This enables available features of the device library.
STM8_DEVICE_DEFINE = "STM8S003"
# Programmer argument for stm8flash (stlink or stlinkv2)
STM8_PROGRAMMER = "stlinkv2"
# Target device argument for stm8flash
STM8_DEVICE_PROG = "stm8s003?3"
# RAM and flash size available on the target device
FLASH_SIZE_BYTES = 8096
INTERNAL_RAM_SIZE_BYTES = 1024
EXTERNAL_RAM_SIZE_BYTES = 0
# Compiled hex file target
HEX_FILE = 'main.ihx'
env = Environment(
CC = 'sdcc',
CPPDEFINES = {
STM8_DEVICE_DEFINE: None,
},
CFLAGS = [
# Building for STM8
'-mstm8',
# Optimisations and standard
'--std-sdcc11',
'--opt-code-size',
],
# SDCC uses .rel instead of .o for linkable objects
OBJSUFFIX = ".rel",
LINKFLAGS = [
'--verbose',
'--out-fmt-ihx',
# Building for STM8
'-mstm8',
# Available resources
'--iram-size', INTERNAL_RAM_SIZE_BYTES,
'--xram-size', EXTERNAL_RAM_SIZE_BYTES,
'--code-size', FLASH_SIZE_BYTES,
],
LIBS = [
'stm8',
],
# Header search paths
# Note that these are relative to the build directory (if SConstruct src='.'')
CPPPATH = [
'',
'.',
'../driver/inc',
],
# Custom variables for use in stm8flash commands
STM8_PROGRAMMER = STM8_PROGRAMMER,
STM8_DEVICE_PROG = STM8_DEVICE_PROG,
)
env.Alias(
'flash',
env.Command(
None,
HEX_FILE,
'stm8flash -c $STM8_PROGRAMMER -p $STM8_DEVICE_PROG -w $SOURCES'
)
)
build = env.Program(
HEX_FILE,
[
'main.c',
]
)
# Remove the build directory when doing a clean (-c)
Clean(build, '../build')
# Only build the hex file by default (don't try to flash, etc)
env.Default(build)
# Build the current directory into a subdir "build"
# This has to be a separate file due to the design of scons
SConscript('SConscript', src='src', variant_dir='build', duplicate=0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment