July 13, 2014

An Assembly Language Delay Routine for ARM Microcontrollers

I'm in the midst of writing some code to initialize an LCD screen. The initialization requires me to send a command, then wait for at least 50 milliseconds, then send more commands.

If you're using an Arduino, this is easy: you call the delay() function. If you're graduating from the Arduino to a more 'bare metal' development environment, you may find yourself looking for this function that doesn't exist on your platform.

Furthermore, if you do a Google search for delay routines on an ARM microcontroller, the near universal reply is, "you should use a hardware timer for that!" (more…)

October 13, 2012

Getting Started with the ARM GCC Compiler on Windows, Part 5: Debugging with OpenOCD

In part 1 of this tutorial series, we installed the GNU ARM GCC toolchain and the Eclipse IDE in order to develop for our ARM microcontrollers. In part 2, we configured the correct compiler and linker settings to get the STM32F0DISCOVERY demo code to build. In part 3, we pared down the demo project into a template to use for all of our future projects for the STM32F0 chip. And in part 4, we build a 'BlinkyLED' program from the template that uses the two LEDs and the user button on the STM32F0DISCOVERY board.

The previous tutorials are all you need to get things up and running on your STM32F0DISCOVERY board... as long as your code works the first time. If your code doesn't work the first time (like, say, my code), you'll want to add some debugging features to your build environment. If you're accustomed to writing code on a desktop computer using a modern IDE such as Visual Studio, you're used to being able to single-step through your code in the debugger from the source code, you're used to examining and modifying the contents of variables when you've broken into your code execution, and you're used to setting breakpoints in your source code. This functionality is (relatively) easy to accomplish on a desktop computer, but things get pretty tricky when trying to do the same things on an embedded platform. The STM32F0 chip has 64K of program space. Shoehorning a complex debugger into that code space along with your application code can be problematic.

Overview of On-Chip Debugging

The solution to this problem is to use what is called "on-chip debugging." On-chip debugging utilizes a small-footprint interface to the microcontroller (two pins in our case) that allow an external debugger to control the processor. Software on our desktop machine can talk to the debugger and give us the rich debugging environment we're used to. In order for Eclipse to talk to our chip, we need two things: we need the hardware to handle communications between the chip and the host computer, and we need the appropriate software on the host computer. The ST-LINK debugger on the STM32F0DISCOVERY board is the hardware part of this interface. The ST-LINK in-circuit debugger/programmer is actually implemented in an STM32F103C8T6 processor  according to both the STM32F0DISCVOVERY schematics and the ST-LINK product documentation. (ST-LINK is sold as a standalone product by ST. We get one "for free" on our STM32F0Discovery board.)

You can learn more about ST-LINK on ST's product page for the standalone version of the device. The documentation is somewhat open to interpretation, but it appears that ST-LINK can communicate with the target microcontroller via one of two interfaces: the SWIM interface, or the JTAG/SWD interface. (Which is confusing because it appears to me that JTAG and SWD are two different interfaces.) The ST-LINK integrated into the STM32F0DISCOVERY board is connected to the STM32F0 via the SWD interface. SWD claims to be a "2 wire" interface, but a common ground is of course necessary as well. In addition, access to the target system's VCC and RESET pins are also handy, but apparently not necessary, for SWD debugging. The SWD connector on the STM32F0DISCOVERY board can be used when using the STM32F0DISCOVERY board as a standalone ST-LINK programmer. The SWD connector is a 6-pin connector with VDD_TARGET, SWCLK, GND, SWDIO, NRST, and SWO pins.

Since the ST-LINK device and the STM32F0 target device are on the same physical circuit board, they already share a common ground and VCC. The other connections used in the Serial Wire Debug (SWD) connection are  the SWCLK (PA14, pin 49), SWO (PB3, pin 55), NRST (pin 7) and SWDAT (PA13, pin 46). It appears that the STM32F0's PA9 and PA10 pins (the USART1 TX and RX ports) are wired between to the ST-LINK device as well, although to the best of my knowledge these pins are unused. (Perhaps a 'serial port debug' USB connection may be available through ST-LINK in the future?) The use of SWO/PB3 is 'reserved' according to the STM32F0DISCOVERY documentation and is governed by solder bridge 22. This bridge is connected on my board. I have no idea what it does.

Let's put this hardware to good use!

Step 1: Download the ST-LINK Utility

ST provides a free utility for working with ST-LINK. Although we won't be using the utility in these tutorials, the software package for the utility includes the USB driver for the ST-LINK, which we need. So download and install the ST-LINK utility, if you haven't done so already in part 2 of this tutorial series. If prompted, allow Windows to install the unsigned driver. You can find the utility from the "Design support" tab of the ST-LINK product page on ST's website.

Step 2: Download OpenOCD

Since we already have the hardware needed to do on-chip debugging, let's get the software we need. Open OCD is an active open-source project designed to translate the signaling between ST-LINK (and, in fact, several other hardware debuggers), and GDB, the GNU Project Debugger. Eclipse will talk to GDB, which will talk to OpenOCD, which will talk to ST-LINK, which will talk to our target chip.

OpenGDB has a project page on sourceforge. Freddie Chopin hosts a download page for the Windows version of OpenOCD. Head over there to grab the latest version of OpenOCD, which is version 0.6.0 as I write this. Extract the files to a convenient location on your hard drive. I used C:\OpenOCD-0.6.0 on my machine.

Step 3: Launch OpenOCD and Connect to the Target Board

Ensure that the STM32F0DISCOVERY board is connected to your computer via the USB cable, and start OpenOCD with the following command:

openocd-0.6.0.exe -f board\stm32f0discovery.cfg

You should see something like this:

By the way, if Windows Firewall asks if you want to unblock OpenOCD from accepting network connections, click on Unblock. OpenOCD opens some TCP ports for Telnet and GDB connections; without unblocking this application, Windows Firewall won't allow you to connect to OpenOCD.

The Info: lines tell us that we've successfully connected to the ST-LINK debugger. Let's execute some commands via OpenOCD and see if we can get output that'll give us some confidence in OpenOCD. Start a telnet session to port 4444, the port on which OpenOCD is listening. Open a (new) command prompt window and type:

telnet localhost 4444

In the telnet window you should get a banner "Open On-Chip Debugger" and a ">" prompt. In the OpenOCD window, you should see "Info: accepting 'telnet' connection from 4444.' (If you're running Windows 7 you may need to install the telnet client: go to Control Panel, then Programs, then Turn Windows features on and off, then check "Telnet Client" and click OK.)

In the telnet window, type the command 'halt' and press Enter. This tells OpenOCD to halt the processor. You should get confirmation that the target is halted:

This is cause for optimism: not only does OpenOCD recognize that it has the processor in the halted state, the PC register (program counter) is a 'sane' value. Remember, Flash ROM starts at 0x08000000. My PC is at 0x0800067a, which is reasonably close to the start of program space.

Dump the processor's registers with the 'reg' command:

You're likely to see different values than I have here, but the fact that OpenOCD can talk to ST-LINK and access the target microcontroller's registers is a supremely good sign. We can single-step the processor with the command 'step':

This concerns me. I've single-stepped the processor three times and the PC hasn't advanced. Now, at the moment, I'm not entirely sure what code I have on this board; I was playing around getting my tools to work with some simple test code. I hope that I have a 'loop forever' construct at 0x0800067a. Let's dump the memory at this location and find out. The mdw/mdh/mdb commands can be used to dump memory as words (32 bits), halfwords (16 bits) or bytes. I entered 'mdb 0x0800067a 0x10' to dump 32 bytes of data at this memory location:

The hex value FE E7 opcode is an unconditional branch to relative location 11111111110, which is a 'branch here' instruction per the examples in section 5.18.2 of the THUMB instruction set document I was able to find. So I'm a lot more comfortable now seeing that my PC isn't advancing when I single-step my code. And I'm convinced that OpenOCD is, in fact, connecting to ST-LINK and getting valid data back from the processor. One last check: I'll halt the processor, manually set the PC register to 0x08000000, and single-step through some code and ensure PC advances:

My Program Counter advanced by two bytes every time I single stepped the processor. This is another Happy Dance moment!

Let's get ambitious and load our BlinkyLEDs code into the STM32F0. In the telnet window, enter the following commands, in order:

flash erase_sector 0 0 last
flash write_image {c:\ARM_Development\STM32F0\BlinkyLEDs\Debug\BlinkyLEDs.elf} 0 elf

The first command halts the processor, which is necessary before erasing the flash memory.

The second command erases the flash memory. The parameters indicate we want to erase flash bank 0 (the only bank of flash on this particular part) from the first sector to the last.

The third command is a flash command to OpenOCD. The command itself is 'write_image.' We give the full path to the .elf file that the linker created. Note that the path is enclosed in curly braces. This is because Tcl, the scripting language used by OpenOCD, was originally written for the Linux environment, which uses the forward slash as a path separator. To convince OpenOCD to recognize the backslash as a path separator, the path must be enclosed in curly braces. The number 0 is the number of bytes to offset the image in memory, and the 'elf' parameter tells OpenOCD the filetype of the image we're uploading.

The last command resets the processor and causes it to begin executing our code. Press the USER button on the dev board and note the results.

And yes... do the Happy Dance. This time for real.

Step 3: Connect Eclipse to OpenOCD

Now, interacting with OpenOCD through a telnet session is nice, but it's not exactly the most efficient way to work. We want Eclipse to interface with our target processor via OpenOCD. This is the last step of our long journey to open-source ARM programming nirvana. We're going to configure Eclipse to talk to arm-none-eabi-gdb, the GDB client. The GDB client will talk to OpenOCD, the GDB server. The GDB server will talk to ST-LINK, and ST-LINK will talk to the STM32F0.

Easy, right?

Let's install the GDB client software into Eclipse. If you don't have it done already, launch Eclipse and open your workspace. (Go ahead and close the two command prompt windows for now.) From the Help menu, select Install New Software. In the Work with dropdown, select "Juno - http://download.eclipse.org/releases/juno." In the list of software packages, expand Mobile and Device Development, and check the "C/C++ GDB Hardware Debugging" package. Click Next, click Next, accept the license agreement, and click Finish. Allow Eclipse to restart when the installation is complete.

 Step 4: Configure a Debug Configuration

The debug environment is called a 'configuration' in Eclipse. On your main toolbar, click the dropdown next to the debug icon and select Debug Configurations.

Click on "GDB Hardware Debugging" in the list of configuration types, and then click the "New" icon in the top left:

This will bring up an interface that will allow you to edit a new debug configuration:

In order to get a configuration working, we must specify a C/C++ application to debug in the first textbox. It seems silly to me to create a separate configuration for each project I work on. The presence of a button labeled "Variables..." suggests that it should be possible to create a debugging configuration that will automagically debug the project that I happen to be working with. Alas, I was not able to figure out how to get this to work, despite quite a bit of effort. Maybe I'll figure it out and post it in a future blog post.

In the absence of variables, specify the project path on the Main tab. In my case, it's:


You want to point to the .elf file so that the debugger has access to the symbols information in there. Your dialog will look similar to this:

On the Debugger tab, change the GDB command by browsing to your local installation of GDB. Check the "Use remote target" checkbox. Specify "Generic TCP/IP" as the JTAG device, the hostname should be "localhost" and the port number should be 3333.

In the Startup tab, note that there are checkboxes for "Reset" and "Halt."

For whatever reason, they don't work. In order to get OpenOCD to halt the processor when we connect, enter the command "monitor reset halt" in the textbox. Leave the rest of the controls alone.

Click the Apply button, then the Close button. To make things easier on you, once again click on the down-arrow next to the Debug icon, and select "Organize Favorites."

Click the Add button, then check the newly created debug configuration. This causes the debug configuration to appear on the drop-down list when you click on the down arrow next to the Debug icon.

 Step 5: Start OpenOCD

Before starting your debug session, you must launch OpenOCD so that the Eclipse GDB client has a server to connect to. Launch OpenOCD with the parameter "-f board\stm32f0discovery.cfg." You may want to create a shortcut for this; you'll be using it often.

Step 6: Debug!

Once OpenOCD is running, click on the down-arrow next to the Debug icon and click on your debug configuration. Eclipse will build your project then debug it. You may be prompted to switch to the Debug perspective; if this happens, check the box to do this every time and select yes. Eclipse will tell OpenOCD to download the newly built code into the target processor, and the processor will be reset and halted. The debug perspective won't show you a whole lot at this point and it may in fact seem that nothing productive has just happened. Click on the OpenOCD window to verify that Eclipse made the connection:

Here you can see that OpenOCD accepted a 'gdb' connection on port 3333. There's no real evidence in the output that the target was flashed with the new code, but it was.

At this point the processor's PC is undefined. The processor is held in reset by ST-Link. When the processor comes out of reset it will read the reset vector and set the program counter. Click the Step Into icon to single step the processor:

The PC will advance to the start of Reset_Handler(), which in my case is 0x08000124. (The address on your system may be different.) Note that Eclipse says there's no source available for Reset_Handler():

I don't know why that is; clearly we did provide source code for this function. It appears that Eclipse can't resolve assembler source code.

Set a breakpoint at the entry to main(). Do this by opening main.c (you can switch to the C/C++ perspective to do this) in the text editor. Right-click in the left margin and select "Toggle Breakpoint."

The margin will show a breakpoint icon at the line where you just set the breakpoint.

Go back to the Debug perspective and click the Resume button (or press F8). Eclipse will run your code until the breakpoint is hit. The source code line that is about to be executed will be highlighted:

You can do all the typical debug functions: you can examine and modify memory and variables, you can single-step through your code, etc.

With the tools that you've configured for yourself through this tutorial series, you should be ready to do ARM development work on the STM32F0Discovery board!


September 21, 2012

Getting Started with the ARM GCC Compiler on Windows, Part 4: Our First Real Project

If you've been following along, in part 1 of this tutorial we installed the free ope-source ARM GCC toolchain, GNU Make, and Eclipse. In part 2, we configured Eclipse to build the demonstration project that ships on the STM32F0DISCOVERY board. In part 3, we pared down the demo project to become a baseline template for future STM32F0 projects.

In this tutorial, we'll start with the template project we created in part 3, and build our first application for the STM32F0DISCOVERY board. This will be a simple project: it will blink the green LED. When the user button is pressed, it'll blink the blue LED instead. Though the project goals are simple, it nevertheless is a good learning exercise. (more…)

September 17, 2012

Getting Started with the ARM GCC Compiler on Windows, Part 3: Making a Template Project

In my first two articles in this series, we configured our build environment to assemble, compile, and link C/C++ projects for the STM32F0DISCOVERY board using free, open-source software. We're using the Eclipse IDE and the ARM GCC compiler. We built the demo project from the sources that ship with the STM32F0DISCOVERY board and got the project to build. We used the ST-LINK utility to upload the project to our dev board and were able to run the program.

Today, let's prepare our project to be the template for all of our future STM32F0 development projects.


September 16, 2012

Getting Started with the ARM GCC Compiler on Windows, Part 2: Creating a FOSS Build Environment for the STM32F0DISCOVERY Board and Building the Demo Project


The STM32F0DISCOVERY board is a great platform for learning ARM microcontroller programming. For only $8 (Digikey, Mouser), you get a dev board with a STM32F051R8T6 microcontroller and an onboard ST-LINK programmer/debugger. Unlike dev boards from other manufacturers, the programmer is designed so that it can be used to program the onboard microcontroller, or it can be used as a standalone programmer. The board can be powered via USB and contains two user LEDs and one user button. All of the microcontroller's I/O pins are brought out to header pins on the dev board. The header pins are single-row pins, so the board can be put into a breadboard. As it ships, the microcontroller runs at 48MHz off an internal RC oscillator, but there are unpopulated pads on the PCB where you can add your own crystals for both the high speed clock and a 32.768 kHz crystal for the real-time clock/calendar.


September 15, 2012

Getting Started with the ARM GCC Compiler on Windows, Part 1: Installing GCC and Eclipse

NOTE 1/13/2018: The information in this post, while it is still valuable and worth reading, is obsolete. Please don't use this technique for building a toolchain for the STM32 series of microcontrollers. I recommend using System Workbench instead, which is still an Eclipse-based platform, but has done the hard integration work for you. I plan on releasing tutorials for this tool soon. (-ish. Grad school starts this week, so any time I had to write tutorials is going to be swallowed up.

Coming from the PIC and AVR world, I've been a little frustrated with the fact that ARM microcontroller vendors don't supply free development tools for their hardware.  I've looked into commercial tools, but as a hobbyist I don't want to pay large sums of money just to tinker around with some new microcontrollers, and I'm reluctant to work with code-limited or otherwise crippled 'trial' or 'lite' versions of these packages. I've known for a while now that there is a free version of GCC that will run on Windows and cross-compile to ARM processors, but haven't really dug in to figure out how to install these tools. There's a surprising lack of clear instructions for the hobbyist to follow.

I found a tutorial written by Dr. Hussam Al-Hertani, an Electronics Technology College instructor, here. I was initially optimistic about this approach. However,the tutorial left me disappointed: Dr. Al-Hertani's approach is to maintain his own makefile, and he's content to use Eclipse as a basic text editor without leveraging the code parsing features that we all expect in a modern IDE. (Edit: Comments in part 2 of his tutorial have addressed this.) By putting include paths in the makefile, Dr. Al-Hertani's approach allows the code to build, but leaves red squiggly error indications all over the source code editor windows because the IDE hasn't parsed the include files as well. I find that these squigglies are distracting, and I find that leveraging the code-parsing features of an IDE helps me become a more effective programmer. So I set out to learn how to extend his approach to make full use of the IDE.

So I set off to teach myself how to install and configure an open-source toolchain for developing and debugging code on ARM microcontrollers. This is the first in a five-part series of blog posts on getting up and running with the STM32F0DISCOVERY board with free, open-source (FOSS) tools. Although I will be using Windows as my operating system, virtually everything in this tutorial series applies to Linux and Mac environments as well.

In future blog posts, I'll expand upon these themes for the STM32F4DISCOVERY board, the LPCXpresso board, and other ARM-based development platforms. And, of course, virtually all of the information in these tutorials will apply to other ARM platforms as well.