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:

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:

JTAG

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

followed by:

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

OpenOCD

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.