STM32F103C8T6 with Eclipse (OpenSTM32) under Mac OSX


The System Workbench for STM32 (SW4STM32) aka. OpenSTM32 aka. AC6 Tools is a set of plugins for the popular Eclipse IDE. There are two ways to install OpenSTM32. The first is to add the plugins to an existing installation of Eclipse, the other is to download a flavor of the Eclipse IDE from the ST homepage which has all the plugins preinstalled. This article explains what my experience was installing the preconfigured Eclipse on a MAC including debugging the program on a bluepill with openocd, the arm-none-eabi-gdb and a ST Link v2 programmer.

I used this article as a foundation for my article.


A word of advice to everybody wanting to use OpenSTM32 on a mac. Make absolutly sure that you are using the latest software packages available. It will not work with outdated software! There is absolutely no backwards compatibility. If your versions are off, the tools just do not work together. They just fail without usefull error messages!

Use the latest version of

Download and Install OpenSTM32

wget --no-check-certificate
chmod +x
Error: Unrecognized option: -d64

If you get this error:

Unrecognized option: -d64
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

The solution is to run the installer with root priviledges.

sudo ./ -m -f
Opening the OpenSTM32
open -a /Applications/Ac6/
Creating a Project

Create a C project as outlined here.

In Eclipse, select File > New > Project > C Project

As Project Type: Empty Project

As Toolchain: Ac6 STM32 MCU GCC

Keep Debug and Release builds checked.

In the wizard step “Target Configuration” switch to the MCU Tab, select

Series: STM32F1

Mcu: STM32F103C8Tx

In the Firmware Configuration Dialog, choose Hardware Abstraction Layer (Cube HAL). The Standard Peripheral Library (StdPeriph) is discontinued and I was not able to get the StdPeriph working.

Error: The Project Importer fails to install

If you get this error:

'tar' failed to extract /Applications/Ac6/ to /Applications/Ac6/

the solution is to manually untar the file:

cd /Applications/Ac6/
sudo bzip2 -d
sudo tar xopf
sudo cp -R /Applications/Ac6/
Error: The compiler fails to install
Failed to extract '/Applications/Ac6/' to '/Applications/Ac6/' (tar returned '1')

The solution is to install the compiler manually:

cd /Applications/Ac6/
sudo bzip2 -d st-gnu-arm-gcc-7-2018-q2-update_gdb-5_4-2016q3-mac.tar.bz2
sudo tar xopf st-gnu-arm-gcc-7-2018-q2-update_gdb-5_4-2016q3-mac.tar
sudo ln -s ./st-gnu-arm-gcc-7-2018-q2-update_gdb-5_4-2016q3-mac ./compiler
Write a small C Program

In order to test debugging you need a small application which is large enough to place some breakpoints in for testing. My example does not make any sense at all so do not question the application too much.

int main(void)
  int i = 0;

  while (1) {


    if (i == 100)
      i = 0;

  return 0;

The application should now compile in Eclipse without errors.

There are two error messages that are apparently caused by the Eclipse code scanner as explained here.

Program “arm-none-eabi-g++” not found in PATH testf7 Project Properties, C++ Preprocessor Include.../Providers, Ac6 SW4 STM32 MCU Built-in Compiler Settings options C/C++ Scanner Discovery Problem
Program “arm-none-eabi-gcc” not found in PATH testf7 Project Properties, C++ Preprocessor Include.../Providers, Ac6 SW4 STM32 MCU Built-in Compiler Settings options C/C++ Scanner Discovery Problem 

If you get these two errors, you can just select and delete them as they are bogus messages more or less and they do not cause your build to fail.

Install gcc-arm-none-eabi on macos

download and unzip the latest version of gdb

sudo cp -R /Users/<username>/Downloads/gcc-arm-none-eabi-9-2019-q4-major /usr/local/gcc_arm

In eclipse in the debug configuration change the gdb command path
Debugger-Tab > GDB command >

Install OpenOCD

brew install open-ocd

OpenOCD Configuration Script

OpenOCD is used in the OpenSTM32 build sequence to establish a connection to the bluepill. gdb will then be used to debug the application over the connection that openocd has established.

To configure how openocd establishes the connection, you have to write a configuration script. In Eclipse, debugging or running an application is done using so called run configurations.

You will create a debug run configuration and specify the path to openocd and the configuration script in the run configuration.

According to this post, there is a bug in OpenSTM32 were the openocd configuration script is not allowed to be located within the Eclipse project but in some other folder. Because of this bug, create the configuration script in some folder but not in the project folder.

I keep my configuration scripts in the folder:


Here is the script that works for me:

source [find interface/stlink-v2.cfg]
transport select "hla_swd"

# added
set BOARDNAME genericBoard

# added
# Enable debug when in low power modes
# Stop Watchdog counters when halt
# STlink Debug clock frequency
#set CLOCK_FREQ 4000
#set CLOCK_FREQ 1000
set CLOCK_FREQ 950
# We do not connect RESET line to stlink, that's why reset is disabled.
#reset_config none
reset_config none separate
source [find target/stm32f1x.cfg]
Create a Run Configuration for Debugging

Open the pull down menu on the Debug button (Button with a green bug on it) in the toolbar. Select “Debug Configurations…”. A dialog opens. Select Ac6 STM32 Debugging and then click the Document button with the small golder plus symbol on it to create a new Debug Run Configuration of the type Ac6 STM32 Debugging.

Here are the settings to make on the Debugger-Tab:

Start Debugging

A breakpoint causes the debugger to pause the microcontroller as soon as it executes the code the breakpoint was set on. You can set breakpoints everywhere which is a bit misleading as for example you can place a breakpoint on an empty line. Obviously there is no code generated for empty lines and the debugger cannot stop on an empty line. It will only stop on lines that actually translate to code that can be executed by the microcontroller. Eclipse will move breakpoints around before starting the application. If a breakpoint is not on a sensical location, Eclipse will move it to the next sensical location.

To set a breakpoint, double click left of a line number. A small blue dot appears. To get rid of a breakpoint, double click the blue dot and it disapears.

In this example, there is a breakpoint on line 25 of our example application:

Whenever i has been incremented to the value 100, the breakpoint will be hit.

Now that you have an application to debug and a breakpoint that makes sense, you can start the debugging session. To start the session, Select your Run Configuration from the Debugging drop down on the toolbar.

Eclipse will compile your application with debug symbols. It will connect to the board using openocd. It will upload the code via the openocd connection and it will start the gnu debugger gdb and connect it to the openocd server which allows gdb to debug the application on the hardware. Eclipse will switch to the debug perspective and it will break on the breakpoint.

The output during application start should be something similar to this:

Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
none separate
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v29 API v2 SWIM v7 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.132308
Info : STM32F103C8Tx.cpu: hardware has 6 breakpoints, 4 watchpoints

In the debugger you can look at variable values and you can single step through the code. If there are errors and you cannot figure out what the issue is by solely thinking about the issue, you can use a debugger to see what decision your code makes and you can figure out what decision making is happening and where the incorrect decisions are made. You can then fix the issues.

Do not forget to write unit tests for your code! Do not get into bad code-and-fix habits! Maybe, if the problem lends itself to it, give test-driven development a shot.

Error: error in final launch sequence

If you get the “error in final launch sequence” – error, make sure you are using the latest gcc-arm-none-eabi. If the versions of the tools do not match, errors such as this one arise.

Error: dyld: Library not loaded: requires version 3.0.0 or later, but

If you get this error message:

dyld: Library not loaded: /usr/local/opt/libusb/lib/libusb-1.0.0.dylib
  Referenced from: /usr/local/opt/libftdi/lib/libftdi1.2.dylib
  Reason: Incompatible library version: libftdi1.2.dylib requires version 3.0.0 or later, but libusb-1.0.0.dylib provides version 2.0.0

then your libusb versions are out-dated.

For me the libusb files in


are all outdated.

You can check this using the otool command:

otool -L /usr/local/opt/libusb/lib/libusb-1.0.0.dylib

  /usr/local/opt/libusb/lib/libusb-1.0.0.dylib (compatibility version 3.0.0, current version 3.0.0)
  /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
  /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
  /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1575.17.0)
  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)

For a correct libusb as outlined above, the output says that the libusb library has a compatibility version of 3.0.0 and a current version of 3.0.0. If your libusb versions deviate, install libusb using brew (brew install libusb) then check where the brew files are (brew list libusb) and then replace the outdated libs with the current libs from brew.

Install a new version of libusb using brew (brew install libusb) then create backups of the four outdated files and copy the new libusb files over

cd /Applications/STMicroelectronics/STM32Cube/STM32CubeProgrammer/
sudo mv libusb-1.0.0.dylib libusb-1.0.0.dylib.backup
sudo cp /usr/local/lib/libusb-1.0.0.dylib .

cd /Applications/STMicroelectronics/STM32Cube/STM32CubeProgrammer/
sudo mv libusb-1.0.0.dylib libusb-1.0.0.dylib.backup
sudo cp /usr/local/lib/libusb-1.0.0.dylib .

cd /Applications/Ac6/
sudo mv libusb-1.0.0.dylib libusb-1.0.0.dylib.backup
sudo mv libusb-1.0.dylib libusb-1.0.dylib.backup
sudo cp /usr/local/lib/libusb-1.0.0.dylib .
sudo cp /usr/local/lib/libusb-1.0.dylib .
Make an LED Blink

Making an LED Blink is described here.

For those coming from a high-level application programming background, a word of advice:

The fact that there is a function called HAL_Delay(500); or osDelay(1000); does not automatically mean that this function will work without setup code! In microcontroller programming, you have to first set up the hardware clock before you can make use of it via waiting functions such as the delay functions!

Same goes for LEDs. You have to first setup the LEDs before you can toggle them. The example given in this article shows how to perform the initial setup which is necessary to periodically make an LED blink. I will duplicate the code here for reference.

#include "stm32f1xx.h"

void SystemClock_Config(void) {

  RCC_ClkInitTypeDef clkinitstruct = { 0 };
  RCC_OscInitTypeDef oscinitstruct = { 0 };

  oscinitstruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  oscinitstruct.HSEState = RCC_HSE_ON;
  oscinitstruct.HSIState = RCC_HSI_OFF;
  oscinitstruct.PLL.PLLState = RCC_PLL_ON;
  oscinitstruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  oscinitstruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&oscinitstruct) != HAL_OK) {
    while (1)

  clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK |
  clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1;
  clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2;
  if (HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2) != HAL_OK) {
    while (1)

int main(void) {



  GPIO_InitTypeDef gpio;
  gpio.Mode = GPIO_MODE_OUTPUT_PP;
  gpio.Pin = GPIO_PIN_13;
  gpio.Pull = GPIO_PULLUP;

  HAL_GPIO_Init(GPIOC, &gpio);

  while (1) {
    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);

In order for this code to compile correctly, you have to add the FreeRTOS utility.

Output an Assembler Listing of the Binary

As outlined here, you can add a command to the post build step to call arm-none-eabi-objdump on your binary to disassemble it and output a listing file.

Open the preferences of your project > C / C++ Build > Settings > Tab: Build Steps > PostBuild Steps > Command.

Append to the command:

; arm-none-eabi-objdump -D "${BuildArtifactFileBaseName}.elf" > "${BuildArtifactFileBaseName}.lst"

Do not forget to prefix the semicolon! The semicolon will append a new command to the post build step.

The result is a .lst file in the debug folder that contains the assembly listing.

STM32F103C8T6 with Arduino IDE

Add the Arduino STM32 core. Goto and download the entire repository as a zip file. Extract the zip file to ~/Documents/Arduino/hardware on a mac, My Documents\Arduino\Hardware on windows. If the hardware folder does not exist, create it. If your zip file extracts to anything other than a folder called Arduino_STM32, rename it to Arduino_STM32.

Add the Arduino SAM Board Manager from within the Arduino IDE. Open Tools > Board > Boards Manager and search for SAM. Install that Board Manager (Arduino SAM Boards).

As Board choose Generic STM32F103 Series. As Variant selectSTM32F103C8 20K Ram 64K Flash. As Upload Method choose serial. CPU speed 72Mhz normal.

Connect the STM 32 microcontroller to the USB serial adapter and that adapter to your PC via usb. The USB Adapter has to be switched to 3.3 Volts using the jumper.

If you look at the Adapter so that the USB connection points away from you and the pins point towards you, we will number the pins from left to right (Pin 1, Pin 2 (TX) , Pin 3 (RX), Pin 4, Pin 5 (VDD), Pin 6 (GND))

The USB adapter will supply power to the microcontroller because it is connected to the PC via USB. To route the power to the microcontroller, connect GND from the adapter to the GND pin on the Microcontroller and the 3.3Volt line to the 3.3V input on the Microcontroller.

For the data transfer via the serial protocol, connect TX and RX. The documentation says that TX is Pin PA9 on the Microcontroller and Pin 2 on the Adapter. RX is Pin PA10 on the Microcontroller and Pin 3 on the Adapter.

In order for the Microcontroller to write data from the serial pins into the flash, place the jumper BOOT 0 into the position labeled with a 1.

In the Arduino IDE, select a blink sketch. File > Examples > A_STM_Examples > Digital > Blink. There is also a General > Blink which you should not use. Use the Digital > Blink.

No change PB1 in the code to PC13 because this is the on board LED on the STM32F103C8T6 boards. There are several occurences in the sketch, replace all of them.

Upload the sketch to the board which makes the LED blink.

As a sidenote, I tried programming the board after putting in on the yellow pins that came with the controller and connecting the USB serial adapter via cables plugged into the breadboard and not directly into the Microcontroller Board. I could not programm the board even once using the yellow pins! It just would not work. I think the proper way is to solder connectors onto the Microcontroller board.

STM32CubeMX on MacOS

Installation on MacOS

Installing STM32CubeMX 5.5.0 on MacOS is not as obvious as it should be. Instead of running the .app file, use the java command to run the .exe file!

java -jar SetupSTM32CubeMX-5.5.0.exe

Source: STM Forums.

This will install the application without admin rights into your user folder: /Users/<username>/

There is an uninstaller in


Starting STM32CubeMX
Creating a Project

Which Toolchain / IDE? Is MDK-ARM correct?

Code Generation


The code is successfully generated under <path> but MDK-ARM V5.27project generation have a problem.

2020-01-22 07:39:02,255 [INFO] ProjectBuilder:1843 - Time for Copy HAL[1] : 141mS.
this is project Generator
2020-01-22 07:39:02,260 [INFO] ProjectBuilder:2428 - Project Generator version: 3.6.0
2020-01-22 07:39:02,702 [INFO] ConfigFileManager:1043 - The Die is : DIE450
2020-01-22 07:39:03,823 [INFO] ToolchainGenerator:364 - [Project Generator] Problem in the project generation
  at generators.KeilGenerator.setDeviceType(
  at convertor.Convertor.generateProject(
  at convertor.Convertor.generateKeilFiles(
  at convertor.Convertor.generate(
  at convertor.Convertor.convert(
  at convertor.Convertor.generate(
2020-01-22 07:39:07,763 [INFO] ConfigFileManager:1872 - mx.scratch is deleted!
2020-01-22 07:39:07,764 [INFO] ProjectBuilder:2595 - Time for Generating toolchain IDE Files: 5505mS.
2020-01-22 07:39:07,764 [ERROR] ProjectBuilder:2601 - Error in Project Generation
2020-01-22 07:39:07,764 [ERROR] ProjectBuilder:666 - Error in Project Generation


STM32 Todo

  • Learn how to decompile a binary
  • Learn about Ethernet:
  • Learn about MBed OS
  • Learn about the MBed online compiler then on the top bar, click on compiler
  • Try the STM32CubeIDE
  • Try to install an Eclipse IDE for STM32

STM32 Compile Applications

Compile on Ubuntu Linux

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

Test the installation:

arm-none-eabi-gcc --version

Should output something similar to this:

arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 7-2018-q3-update) 7.3.1 20180622 (release) [ARM/embedded-7-branch revision 261907]
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO


cd ~
cd dev
mkdir helloworld
cd helloworld
vi main.c

paste this text:


while (1);

Compile the program:

arm-none-eabi-gcc -std=gnu99 -g -O2 -Wall -mlittle-endian -mthumb -mthumb-interwork -mcpu=cortex-m0 -fsingle-precision-constant -Wdouble-promotion --specs=nosys.specs main.c -o main.elf

You will get an .elf file. It is not an .bin file and cannot be flashed.

Check the elf file

arm-none-eabi-readelf -h main.elf

Convert the .elf file to .bin (Removes the .elf metadata and only leaves raw machine code for the microcontroller to execute)

arm-none-eabi-objcopy -O binary main.elf main.bin

You can now flash the bin file using st-link.
Connect the board using usb.
Check that the board is connected:

/home/wbi/dev/stlink/build/Release/st-info --probe

Flash the binary onto the board. Warning: Flashing a binary onto the board will override the previous content of the board without performing any backup! The previous content is lost and cannot be brought back! If you want to safe the content, first read the flash. Reading the flash is described in another article.

st-flash write main.bin 0x08000000

STM32 Reading the flash memory

Why read the flash

Before flashing my own software into the stm32, I wanted to download and store the preinstalled example program. To download the preinstalled application, it is necessary to read the 512kb flash memory to a file on disk.

Mac OS

On mac, the easiest way to read the 512KB flash is using the STM32CubeProg application which is available for Mac, Linux and Windows. It is available from here. Please do not confuse the STM32CubeProg (STM32 Cube Programmer) tool with the STM32CubeIDE (available here).

On Mac, the only problem is installing the STM32CubeProg. Clicking the .app file from the zip does nothing. Instead the only way to install the application is to use the tip from this page. The post says to execute a java command on the .exe file on mac which actually works and installs the application just fine.

sudo java -jar SetupSTM32CubeMX-4.22.0.exe

The STM32CubeProg allows to select an address to read from and an amount of bytes to read.

The flash has a size of 512 kilobyte. The hex equivalent of 512kb is 0x80000. Reading 0x80000 from the address 0x08000000 using a Data Width of 32bit, will read the flash content.

First plugin the STM32 board using a USB-Cable. When starting up the STM32CubeProg application, it says it is not connected. Click the connect button. The application will automatically detect your board and set correct parameters. It will prefill the address field with 0x08000000 and the Size with 0x400. Replace the size by 0x80000 to read 512kb. Click the Read button and wait until the application does refresh itself. Then, toggle the Read button from Read to Save As… by opening the dropdown and selecting Save As… from the options. Then click the button and store the file onto your harddrive.


On Ubuntu Linux, you can install a USB driver and the st-link application to access the flash of the STM32 Nucleo F446RE.

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

Test the installation

arm-none-eabi-gcc --version

Should output something similar to this:

arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 7-2018-q3-update) 7.3.1 20180622 (release) [ARM/embedded-7-branch revision 261907]
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO

Install the USB driver:

sudo apt-get install libusb-1.0-0-dev

Install st link by checking out the git repository and compiling the source code:

git clone
cd stlink
make release
cd build/Release

/home/wbi/dev/stlink/build/Release/st-info --version
/home/wbi/dev/stlink/build/Release/st-info --flash
/home/wbi/dev/stlink/build/Release/st-info --sram
/home/wbi/dev/stlink/build/Release/st-info --descr
/home/wbi/dev/stlink/build/Release/st-info --pagesize
/home/wbi/dev/stlink/build/Release/st-info --chipid
/home/wbi/dev/stlink/build/Release/st-info --serial
/home/wbi/dev/stlink/build/Release/st-info --hla-serial
/home/wbi/dev/stlink/build/Release/st-info --probe

Read the flash
stlinkv2 command line: ./st-flash [--debug] [--reset] [--serial <serial>] [--format <format>] [--flash=<fsize>] {read|write} <path> <addr> <size>
st-flash --format binary read mydump.bin 0x08000000 0x100
/home/wbi/dev/stlink/build/Release/st-flash --format binary read /home/wbi/temp/stmnucleof446RE/mydump.bin 0x08000000 0x200
/home/wbi/dev/stlink/build/Release/st-flash read /home/wbi/temp/stmnucleof446RE/out.bin 0x08000000 0x80000