STM32 Primer - The hardware
The ARM Cortex™‑M based STM32 family of microcontrollers from ST is a popolar choice for many design companies and embedded system hobbyists due to its price/performance ratio advantage.
What I have on hand here is a STM32F103RB from the medium-density performance line, which has 120 Kbytes of Flash and 20 Kbytes of SRAM. The PCB has a bunch of devices connected to the peripherals. But what's of interest to us in this primer are:
- A USB connector - supply power to the micro through a 3.3V linear regulator, also connected to a USB-to-serial driver for the UART example.
- A 8 MHz crystal to produce the main clock.
- An LED connected to bit 8 of Port A - for the LED blinking example.
- BOOT0 and BOOT1 connected to two jumpers so that the boot mode can be configured - in our case BOOT0 needs to be connected to GND so that the boot memory space (starting 0x0000 0000) is aliased to the main Flash memory (starting 0x0800 0000).
- JTAG connector - for programming and debugging.
Among other things on the board are - a 32.768 Khz crystal for the RTC, a 3V Lithium battery for the RTC and backup registers when VDD is not present, etc. Here is a picture:
The STM32 does have a production programmed bootloader located in the System memory (starting 0x1FFF F000), so it can be programmed via UART, USB or CAN when the System memory is selected as boot space by putting BOOT0 to 1 and BOOT1 to 0. But since my board comes with a J-Link USB JTAG adaptor, I am going to use that to reprogram the micro.
First download the J-Link software pack for Linux here. The version I have is v4.41g. When finished do:
me@pandafruits:~$ tar -xzvf JLink_Linux_V441g.tgz
There is detailed instruction on how to get it working in the README file. But basically, first make sure libraries 'libusb' and 'libreadline' are installed; then do:
me@pandafruits:~/JLink_Linux_V441g$ sudo cp libjlinkarm.so.* /usr/lib
me@pandafruits:~/JLink_Linux_V441g$ sudo ldconfig
Now try run it by executing the 'start' file (use 'chmod +x' first if necessary) with root:
me@pandafruits:~/JLink_Linux_V441g$ sudo ./start ./JLinkExe: error while loading shared libraries: libreadline.so.5: cannot open shared object file: No such file or directory
It's complaining about not being able to find 'libreadline.so.5' in '/lib/'. On my 32-bit Ubuntu machine, this library is actually in '/lib/i386-linux-gnu/' and the version is higher. So now try creating a symbolic link in '/lib/' pointing to that file:
me@pandafruits:~$ sudo ln -s /lib/i386-linux-gnu/libreadline.so.6 /lib/readline.so.5
After this, try running 'start' again:
me@pandafruits:~/JLink_Linux_V441g$ sudo ./start SEGGER J-Link Commander V4.41g ('?' for help) Compiled Jan 27 2012 19:11:22 DLL version V4.41g, compiled Jan 27 2012 19:11:21 Firmware: J-Link ARM V8 compiled Jan 12 2012 20:43:19 Hardware: V8.00 S/N: ******** Feature(s): RDI,FlashDL,FlashBP,JFlash,GDBFull VTarget = 3.319V Info: TotalIRLen = 9, IRPrint = 0x0011 Info: Found Cortex-M3 r1p1, Little endian. Info: TPIU fitted. Info: FPUnit: 6 code (BP) slots and 2 literal slots Found 2 JTAG devices, Total IRLen = 9: #0 Id: 0x3BA00477, IRLen: 04, IRPrint: 0x1, CoreSight JTAG-DP (ARM) #1 Id: 0x16410041, IRLen: 05, IRPrint: 0x1, STM32 Boundary Scan Cortex-M3 identified. JTAG speed: 100 kHz J-Link>
It seems now the JTAG is probing the micro OK. Type in '?' gives a list of available commands to use. But we are not going to use any of those commands, all we do here is to make sure the hardware works, so just type 'q' to exit. However, we are not quite done yet. As later on we'll use OpenOCD for programming and debugging, we need to install the '.rules' file in '/etc/udev/rules.d/' so OpenOCD has permissions to the debug adaptor. Just follow the instructions in README. Copy '45-jlink.rules' into '/etc/udev/rules.d/':
me@pandafruits:~/JLink_Linux_V441g$ sudo cp 45-jlink.rules /etc/udev/rules.d/
Then create group 'plugdev' (if not already exists), add yourself to the group and reboot machine:
me@pandafruits:~$ sudo groupadd plugdev me@pandafruits:~$ sudo usermod -a -G plugdev <Username> me@pandafruits:~$ sudo reboot
Next step is to install and configure OpenOCD. Depending on the JTAG adaptor you have, you may need to download and compile the source yourself. For me, I only needed to install it from Ubuntu's repository, as the USB JLINK based adaptors are supported in that version (v0.5.0):
me@pandafruits:~$ sudo apt-get install openocd
To invoke the OpenOCD server:
me@pandafruits:~$ openocd -f interface/jlink.cfg -f target/stm32f1x.cfg Open On-Chip Debugger 0.5.0 (2011-12-03-08:57) Licensed under GNU GPL v2 For bug reports, read http://openocd.berlios.de/doc/doxygen/bugs.html Warn : Adapter driver 'jlink' did not declare which transports it allows; assuming legacy JTAG-only Info : only one transport option; autoselect 'jtag' 1000 kHz adapter_nsrst_delay: 100 jtag_ntrst_delay: 100 cortex_m3 reset_config sysresetreq Info : J-Link initialization started / target CPU reset initiated Info : J-Link ARM V8 compiled Jan 12 2012 20:43:19 Info : J-Link caps 0xb9ff7bbf Info : J-Link hw version 80000 Info : J-Link hw type J-Link Info : J-Link max mem block 9440 Info : J-Link configuration Info : USB-Address: 0x0 Info : Kickstart power on JTAG-pin 19: 0x0 Info : Vref = 3.319 TCK = 1 TDI = 0 TDO = 1 TMS = 0 SRST = 0 TRST = 0 Info : J-Link JTAG Interface ready Info : clock speed 1000 kHz Info : JTAG tap: stm32.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3) Info : JTAG tap: stm32.bs tap/device found: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1) Info : stm32.cpu: hardware has 6 breakpoints, 4 watchpoints
This indicates OpenOCD started successfully and is running as a daemon, waiting for connections from clients via Telnet or GDB etc. By the way, instead of typing 'openocd -f interface/jlink.cfg -f target/stm32f1x.cfg', a better way to invoke OpenOCD is to put the following two lines in a file named 'openocd.cfg', then simply type the command 'openocd' from the directory that contains the 'openocd.cfg' file. OpenOCD will try to read the file's contents when started:
source [find interface/jlink.cfg] source [find target/stm32f1x.cfg]
Now we try to talk to the OpenOCD server using telnet. With the deamon still running, open a new terminal and do:
me@pandafruits:~$ telnet localhost 4444 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Open On-Chip Debugger >
Now OpenOCD is ready to execute commands issued from telnet. This is indicated by a new Info line in the terminal showing status of OpenOCD:
Info: accepting 'telnet' connection from 4444
Finally, we'll try a couple of commands over telnet to make OpenOCD erase the micro's Flash. So in the telnet terminal, do:
> reset halt JTAG tap: stm32.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3) JTAG tap: stm32.bs tap/device found: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1) target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x08000008 msp: 0x20005000 > flash probe 0 device id = 0x20036410 flash size = 128kbytes device id = 0x20036410 flash size = 128kbytes flash 'stm32f1x' found at 0x08000000 > stm32f1x mass_erase 0 stm32x mass erase complete >
You can see that the erase completed successfully. The OpenOCD server daemon also shows the same information:
Info : JTAG tap: stm32.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3) Info : JTAG tap: stm32.bs tap/device found: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1) target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x08000008 msp: 0x20005000 Info : device id = 0x20036410 Info : flash size = 128kbytes Info : device id = 0x20036410 Info : flash size = 128kbytes flash 'stm32f1x' found at 0x08000000 stm32x mass erase complete
When all done, 'Ctrl+C' to terminate the OpenOCD server. Telnet terminal shows:
> Connection closed by foreign host.
Now that the hardware is working, we'll move on to install the GNU toolchain next.