Introduction: STM32F103RB in Arduino and Beyond

The time has come for me to try one of the 32-bit ARM microcontrollers available these days. I'm not going to give up with 8bit world, no way, but I think it is very interesting to expand my knowledge in this area.

These microcontrollers have more speed, more peripherals and more capabilities, with the drawback of significant complexity (comparing with 8 bit MCU's).

For (some) subjective reasons, price/performance but most important: easy to find (for my location) stand-alone chips. So, I don't spent much time and I choose to go further with STM32F103RBT6, which I found both a cheap development board and the opportunity to buy easily stand-alone chips.

Development board that I chose is "ARM Cortex - M3 STM32F103RBT6 Development Board with USB Power Supply" from http://www.gearbest.com/development-boards/pp_64517.html at $14.25 - free shipping.

Even if in the name there is the phrase "USB Power Supply" in fact it is more than that:USB Socket D- and D+ are connected to pins PA11 and PA12. And there are one pull-up resistor (R18 = 1.5k) from D+ to 3.3v that can be activated with jumper J6 when we develop USB Device projects (full speed device).

.

Step 1: Microcontroller

As we can see from the graphs above, our microcontroller ranks in the middle, in terms of performance and memory. These charts are screenshots from ST site:

STM32F103RBT6 overview:

ARM® CortexTM-M3 core: CPU frequency: 72MHz

Memory:

  • Flash - 128 Kbytes
  • SRAM - 20 Kbytes

Timers:

  • General purpose: 3 timers (16-bit)
  • Advanced Control: 1 timer ( SysTick timer 24-bit)

Communication:

  • SPI 2 (up to 18 Mbits/s)
  • I2C 2 (support SM Bus 2.0/PM Bus)
  • USART 3 (one up to 4.5 Mbit/s, other two up to 2.25 Mbit/s)
  • USB 1 (compatible with the USB Full-speed 12 Mbs)
  • CAN 1 (up to 1 Mbit/s)

GPIOs: 49

ADC 12-bit: 2 ADC - 16 channels

RTC (real-time clock): 1

DMA: 7 Channels

Internal Temperature sensor: 1 (internally connected to the ADC_IN16 input channel)

Operating voltage: 2.0 - 3.6 V

Package: LQFP64

Step 2: Board

I must say from the start that I am very satisfied with this board. I like the minimal design, what gives me the freedom to choose how and what devices to connect.

Anyway board has the following features:

  • 1 Serial RS232 Connector (with MAX3232, can be connected to USART1 or USART2 with jumpers J4)
  • 1 USB Connector (wired to PA11 and PA12)
  • 1 JTAG Connector (2x10Pins)
  • Reset push-button
  • 1 Power LED
  • 2 User push-buttons (wired to PC0 and PC1)
  • 2 LEDs (wired toPB8 and PB9)
  • J5 Jumper for selecting power supply (from USB connector or JTAG connector)
  • J6 Jumper for activating USB Pull-up resistor (R18=1.5k)
  • BOOT0 and BOOT1 jumpers for selecting boot mode
  • LC filtering for VDDA (L1 and C6)

Also I attached board schematic in PDF format.

Step 3: Booting and Flashing

Boot modes and flashing are closely related, so I'll talk about them together.

Flashing STM32 can be done in various ways:

  • System / factory bootloader (USART1)
  • JTAG/SWD interface (using compatible dedicated programmer)
  • Custom bootloaders (USART or USB)

Because I do not have (yet) a dedicated programmer I will go further with first option (system bootloader).

All STM32 microcontrollers have a built-in bootloader which can be activated by a specific pin configuration BOOT1 and BOOT0.

For STM32F103B at startup, boot pins are used to select one of three boot options:

  • Boot from User Flash - Boot0=0 and Boot1=x
  • Boot from System Memory - Boot0=1 and Boot1=0
  • Boot from embedded SRAM - Boot0=1 and Boot1=1

So I set the board as follows:

  • Boot0=1 Boot1=0 (jumpers J2 and J1)
  • RS232 Connector to USART1 (jumper J4)

Step 4: Flashing Program

Since my intention was to make this board work in Arduino IDE, I chose to use an open source application stm32flash from https://code.google.com/p/stm32flash/ . Is the same tool used by Arduino STM32 project from here: https://github.com/rogerclarkmelbourne/Arduino_ST...

stm32flash usage:

Usage: ./stm32flash [-bvngfhc] [-[rw] filename] /dev/ttyS0
-b 		rate Baud rate (default 57600)
-r 		filename Read flash to file
-w 		filename Write flash to file
-u 		Disable the flash write-protection
-e n 		Only erase n pages before writing the flash        
-v 		Verify writes     
-n 		count Retry failed writes up to count times (default 10)       
-g 		address Start execution at specified address (0 = flash start)        
-s 		start_page Flash at specified page (0 = flash start)
-f 		Force binary parser
-h 		Show this help    
-c 		Resume the connection (don't send initial INIT)

Example command for get device information:

  • for Windows:stm32flash COM3
  • for Linux ./stm32flash /dev/ttyS0

To test that everything is ok, you can run some precompiled examples:

    • Example1.bin will flash alternately the two LEDs of the board in main loop with delay.
    • Example2.bin will flash alternately the two LEDs of the board using timer.
    • Example3.bin will fade alternately the two LEDs of the board using PWM.
    stm32flash COM3 -w Example1.bin -g 0x0
    stm32flash COM3 -w Example2.bin -g 0x0
    stm32flash COM3 -w Example3.bin -g 0x0

    -g 0x0 will run program after flashing

    NOTE: After flashing and running an example you must push reset button to be able to flash another example.

    Step 5: Install STM32F103RB in Arduino IDE

    To make it work in Arduino IDE 1.5.8 I choose project Aduino STM32 which I found on GitHub at the following link:https://github.com/rogerclarkmelbourne/Arduino_STM32. I have not tested with versions > 1.6.x , since these versions are very new and I have not yet accommodated with their peculiarities.

    I put here an archive "ready to use" with additions already made for this specific board. I left intact the entire original project structure. I just added folder (made after generic_stm32f103r):

    [...arduino...]\hardware\arduino\STM32F1\variants\generic_stm32f103rb

    and I append board definition in file:

    [...arduino...]\hardware\arduino\STM32F1\boards.txt

    with this (also made after Generic STM32F103R definitions):

    ########################### Generic STM32F103RB  ###########################<br>
    genericSTM32F103RB.name= Generic STM32F103RB series
    genericSTM32F103RB.build.variant=generic_stm32f103rb
    genericSTM32F103RB.build.vect=VECT_TAB_ADDR=0x8000000
    genericSTM32F103RB.build.core=maple
    genericSTM32F103RB.build.board=GENERIC_STM32F103RB
    genericSTM32F103RB.upload.use_1200bps_touch=false
    genericSTM32F103RB.upload.file_type=bin
    genericSTM32F103RB.upload.auto_reset=true
    
    genericSTM32F103RB.menu.device_variant.STM32F103REB=STM32F103RB
    genericSTM32F103RB.menu.device_variant.STM32F103REB.build.cpu_flags=-DMCU_STM32F103RB 
    genericSTM32F103RB.menu.device_variant.STM32F103REB.upload.maximum_size=131072
    genericSTM32F103RB.menu.device_variant.STM32F103REB.upload.ram.maximum_size=20480
    genericSTM32F103RB.menu.device_variant.STM32F103REB.upload.flash.maximum_size=131072
    genericSTM32F103RB.menu.device_variant.STM32F103REB.build.ldscript=ld/stm32f103rb.ld
    
    #---------------------------- UPLOAD METHODS ---------------------------
    genericSTM32F103RB.menu.upload_method.serialMethod=Serial
    genericSTM32F103RB.menu.upload_method.serialMethod.upload.protocol=maple_serial
    genericSTM32F103RB.menu.upload_method.serialMethod.upload.tool=serial_upload
    
    genericSTM32F103RB.menu.upload_method.STLinkMethod=STLink
    genericSTM32F103RB.menu.upload_method.STLinkMethod.upload.protocol=STLink
    genericSTM32F103RB.menu.upload_method.STLinkMethod.upload.tool=stlink_upload
    genericSTM32F103RB.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1

    Note: These changes are already made in the attached archive. You just need to unzip the archive content and to put in place. (see images at this step)

    Step 6: First Tests With STM32 Installed

    Now we can start the Arduino IDE and select Generic STM32F103RB like in picture above.

    First test I did was blink variant:

    void setup() {
    	pinMode(PB8, OUTPUT);
    	pinMode(PB9, OUTPUT);
    }
    void loop() {
    	digitalWrite(PB8,!digitalRead(PB8));
    	digitalWrite(PB9,!digitalRead(PB8));
    	delay(1000); 
    }

    Also I test 16x2 LCD Module - 5V

    #include <LiquidCrystal.h>
    #define p_RS PC12 
    #define p_EN PC10
    #define p_D4 PC0
    #define p_D5 PC1
    #define p_D6 PC2
    #define p_D7 PC3
    
    LiquidCrystal lcd(p_RS, p_EN, p_D4, p_D5, p_D6, p_D7);
    
    void setup() {
    	lcd.begin(16, 2);
      	lcd.print("LCD Init. OK");
      	delay(1000);
      	lcd.clear();
      	lcd.print("STM32 - Arduino");
      	lcd.setCursor(0, 1);
      	lcd.print("LCD 16x2 - 5V");
    } 
    void loop() {
    }

    I attached here bin files for these examples in zip file.

    Step 7: Beyond Arduino - Arm-none-eabi-gcc

    At this point I must admit that I cheated a little ... When I started working with this board (and with STM32 MCU), I have not tried to work with Arduino in the first. Instead I tried to find some tools to compile and run some examples, and set my own way to work with these MCUs.

    I spent a few days (after google: "stm32 toolchain") trying to of guiding me in the multitude of possibilities. There are many... You can look here: What_should_I_use_to_develop_on_STM32?

    No longer talking, I decided to start from ground, because I want to understand what's going on at low level.

    So, I download GNU Tools for ARM Embedded Processors (ARM employees are maintaining this project). There are precompiled versions for Windows, Linux and Mac (also source code). After installation make sure that the bin folder of arm-none-eabi-gcc is inluded in PATH enviroment variable. We can test this with command:

    arm-none-eabi-gcc -v 
    

    or:

    arm-none-eabi-gcc --help

    you must see something like screenshots above.

    Step 8: STM32F10x Standard Peripherals Library

    Next step was to download STM32F10x Standard Peripherals Library from ST website:

    http://www.st.com/web/en/catalog/tools/PF257890. (STM32F10x_StdPeriph_Lib_V3.5.0)

    From their description: "This library is a firmware package which contains a collection of routines, data structures and macros covering the features of STM32 peripherals. It includes a description of the device drivers plus a set of examples for each peripheral. The firmware library allows any device to be used in the user application without the need for in-depth study of each peripheral’s specifications."

    This library is helpful to begin the study of these microcontrollers (so I will continue to use, until I will understand better whole story), but this level is not the lowest possible. There is another (lowest) level, working directly with MCU registry; I am not confident enough to work at this level... yet.

    So, in the next steps, I will use STM32F10x_StdPeriph_Lib_V3.5.0.

    An interesting thing to note is the existence of the help file: stm32f10x_stdperiph_lib_um.chm (it is worth studying)

    Step 9: Setting Enviroment

    Now armed with the these tools:

    • arm-none-eabi-gcc
    • STM32F10x Standard Peripherals Library
    • a text editor (I use Notepad++)

    I started building a working enviroment to compile my first project.

    "Hello World" for microcontrollers is nearly always some blink LEDs.

    Because it is hard to explain in detail the whole structure of my set-up, I put a picture above with my folders tree.

    In the examples that follow I use hardcoded path only to make compiler, assembler and linkeroptions easily spotted. In fact I modified "my working enviroment" and replace all shell/environment variables with hardcoded values. (For the same reason I did not use makefile)

    To make these examples work you must make a folder under D:\ named STM32Projects and unzip PhoenixProject.zip here. You should get a structure like the one in the picture above."

    Note: "Phoenix Project" is the working name for this personal project. (I guess there will be many changes and iterations until a final form)

    Step 10: Examples

    I make only four examples:

    Example 1: Will start both LEDs will flash alternately in main loop using Delay().

    Example 2: Will start both LEDs will flash alternately with Timer2 Interrupt.

    Example 3: Will start both LEDs fade alternately with Timer4 Channel3 / Channel4 PWM output

    Example 4: Will send 'Hello world!' string to USART1

    Examples were made by the examples that I've found in STM32F10x Standard Peripherals Library.

    Each example contains a file compile_ex1.bat, compile_ex2.bat, ... compile_ex4.bat which can be used to compile.

    After compilation you will find in the current directory many *.o files; also *.bin and *.hex and *.elf files.

    Bin or hex files can be used with stm32flash utility to upload and run

    Step 11: Finally

    This Instructables shows my subjective experience, in my attempt to get used with these types of microcontrollers.

    The solutions and methods presented here are not the most optimal. I think it will be useful anyway, for someone who is at the same stage; representing a starting point and/or a proof of concept.

    Between the two approaches, working in Arduino and working directly with gcc, there are lot of possibilities both commercial and open source.

    I hope you liked.

    Have fun!

    Later edit: A comment from Roger Clark that I am glad to add to my article:

    Hi Silvius Just to let let your readers know, that they can now use version 1.6.9 of the Arduino IDE. We also have a forum www.stm32duino.com for the Arduino on STM32 community. When I get time I will also add this board to the wiki (http://wiki.stm32duino.com ) and link to this page.