{"id":994,"date":"2013-03-08T00:00:00","date_gmt":"2013-03-07T23:00:00","guid":{"rendered":"https:\/\/www.fussylogic.co.uk\/blog\/?p=994"},"modified":"2016-05-18T11:34:53","modified_gmt":"2016-05-18T10:34:53","slug":"getting-started-with-the-stm32f0-discovery","status":"publish","type":"post","link":"https:\/\/www.fussylogic.co.uk\/blog\/?p=994","title":{"rendered":"Getting Started With The STM32F0 Discovery"},"content":{"rendered":"<h2 id=\"introduction\">Introduction<\/h2>\n<p>I\u00e2\u20ac\u2122ve added another nice cheap dev board to my collection, the <a href=\"http:\/\/www.st.com\/web\/catalog\/tools\/FM116\/SC959\/SS1532\/PF253215\">STM32F0 Discovery<\/a>, which I got from RS in the UK for \u00c2\u00a3. It\u00e2\u20ac\u2122s an SGS Thompson (ST) kit, based around their <a href=\"http:\/\/www.st.com\/web\/catalog\/mmc\/FM141\/SC1169\/SS1574\/LN7\/PF251901\">STMF051R8T6<\/a> device, which is in turn based on an <a href=\"http:\/\/www.arm.com\/products\/processors\/cortex-m\/cortex-m0.php\">Arm Cortex M0<\/a>.<\/p>\n<p>I like this sort of dev board so much because they allow you to work on the hardest part of getting going with a new embedded microcontroller, cheaply \u00e2\u20ac\u201c getting the first program compiled, programmed into the device, and running. It\u00e2\u20ac\u2122s hard because you have to piece together all the software components, a dev environment, and some sort of programmer. This is made even harder if you\u00e2\u20ac\u2122re a Linux user, as (for a reason I don\u00e2\u20ac\u2122t understand) chip manufacturers promote closed source, expensive compilers like Keil and IAR over free GCC based systems. They could even use Eclipse if they felt a graphical interface was necessary. <em>C\u00e2\u20ac\u2122est la vie<\/em>. Dev kits for new microcontrollers used to run into the hundreds of pounds, when all you really want is a board with a powersupply, some pins and a header for programming\/debugging. That\u00e2\u20ac\u2122s exactly what these new style dev boards are.<\/p>\n<p>For a while I was playing around with a similar device\/board from Texas Instruments \u00e2\u20ac\u201c their <a href=\"http:\/\/www.ti.com\/ww\/en\/launchpad\/stellaris_head.html\">Stellaris Launchpad board<\/a>, which I chose because I like the <a href=\"http:\/\/www.ti.com\/tool\/msp-exp430g2\">MSP430 Launchpad<\/a> board so much \u00e2\u20ac\u201c but as I investigated it seemed like TI have put uncomfortable licenses on a few of their example files, and have made it not straight forward to program from Linux. (I\u00e2\u20ac\u2122m also not very impressed with their attitude to not supporting SDCC\/GCC for their ZigBee and Bluetooth Low Energy software stacks). So, I was pleased to be told about this discovery board from ST (to be fair these two are slightly different, this ST board is a Cortex-M0 device; and the Stellaris Launchpad is a Cortex-M4 device, but there\u00e2\u20ac\u2122s a <a href=\"http:\/\/www.st.com\/web\/catalog\/tools\/FM116\/SC959\/SS1532\/PF252419\">Cortex-M4 discovery board<\/a> if we outgrow the STM32F0).<\/p>\n<p>These discovery boards are between \u00c2\u00a35 and \u00c2\u00a310 pounds; and the chips themselves, in one-off prices are just over \u00c2\u00a32 \u00e2\u20ac\u201c very pleasant; and you get a lot of CPU for your buck.<\/p>\n<p>Enough waffle. On to the meat.<\/p>\n<h2 id=\"programming-the-flash-memory\">Programming the flash memory<\/h2>\n<p>On the board is an STM32 (the product line) F (general purpose) 051 (Cortex-M0, \u00e2\u20ac\u0153051\u00e2\u20ac\u009d range of devices) R (64-pin) 8 (8kB RAM; 64kB flash) T (LQFP) 6 (-40 to 84 working temp). The ST website, has a datasheet (which isn\u00e2\u20ac\u2122t a lot of use) and, more important, the reference manual (all 748 pages) easily downloadable. On the whole: points for ST, I got the data I wanted, and there\u00e2\u20ac\u2122s lots of it.<\/p>\n<p>Plugging the board in to a USB slot, powers it up and runs the sample program. An LED flasher. Good.<\/p>\n<p>Make sure you\u00e2\u20ac\u2122ve got access to the USB device, by adding a rule like this to your <code>\/etc\/udev\/rules.d\/<\/code> directory (use <code>lsusb<\/code> to check the vendor and product ids):<\/p>\n<pre><code># 51-stm32-discovery.rules\nATTRS{idVendor}==&quot;0483&quot;, ATTRS{idProduct}==&quot;3748&quot;, MODE=&quot;0660&quot;, GROUP=&quot;plugdev&quot;<\/code><\/pre>\n<p>Reload the rules with <code>\/etc\/init.d\/udev reload<\/code>.<\/p>\n<p>We can be pretty confident that, being an ARM core, that we\u00e2\u20ac\u2122ll be able to find a compiler for Linux (ARM being <em>everywhere<\/em> now, and the big boy varieties actually run Linux), so our first hurdle is a programmer. Fortunately, some clever chaps have already done the hard work \u00e2\u20ac\u201c <a href=\"http:\/\/www.st.com\/st-web-ui\/static\/active\/en\/resource\/technical\/document\/reference_manual\/DM00031936.pdf\">openocd<\/a>. Double fortunately, it\u00e2\u20ac\u2122s already in Debian, with STM32F0 discovery support (the power of open source communities).<\/p>\n<p>OpenOCD is very flexible, and does far more than just what we\u00e2\u20ac\u2122ll use it for, so it can appear complicated, but it\u00e2\u20ac\u2122s just recipes that you can fire and forget after they\u00e2\u20ac\u2122re written. Here\u00e2\u20ac\u2122s my <code>Makefile<\/code> for running OpenOCD:<\/p>\n<pre><code># Makefile.ocd\nOPENOCD_SCRIPT_DIR := \/usr\/share\/openocd\/scripts\nBINARY := $(shell pwd)\/$(BINARY)\n\ndefault:\n    @echo &quot;make read BINARY=yourbinary.bin&quot;\n    @echo &quot;make program BINARY=yourbinary.bin&quot;\n\nread:\n    @[ ! -e &quot;$(BINARY)&quot; ] || (echo &quot;$(BINARY) already exists, won&#39;t overwrite&quot; &amp;&amp; exit 1)\n    openocd \\\n        -f $(OPENOCD_SCRIPT_DIR)\/board\/stm32f0discovery.cfg \\\n        -c &quot;init&quot; \\\n        -c &quot;reset halt&quot; \\\n        -c &quot;sleep 100&quot; \\\n        -c &quot;wait_halt 2&quot; \\\n        -c &quot;dump_image $(BINARY) 0x08000000 65536&quot; \\\n        -c &quot;reset halt&quot; \\\n        -c &quot;shutdown&quot;\n\nprogram: $(BINARY)\n    openocd \\\n        -f $(OPENOCD_SCRIPT_DIR)\/board\/stm32f0discovery.cfg \\\n        -c &quot;init&quot; \\\n        -c &quot;reset halt&quot; \\\n        -c &quot;sleep 100&quot; \\\n        -c &quot;wait_halt 2&quot; \\\n        -c &quot;flash write_image erase $(BINARY) 0x08000000&quot; \\\n        -c &quot;sleep 100&quot; \\\n        -c &quot;verify_image $(BINARY) 0x08000000&quot; \\\n        -c &quot;sleep 100&quot; \\\n        -c &quot;reset halt&quot; \\\n        -c &quot;shutdown&quot;<\/code><\/pre>\n<p>Our <code>openocd<\/code> command read 65536 bytes starting at device memory address 0x08000000. That address can be seen in the memory map in the <a href=\"http:\/\/www.st.com\/st-web-ui\/static\/active\/en\/resource\/technical\/document\/reference_manual\/DM00031936.pdf\">reference manual<\/a> as being the address that the internal flash is mapped to. Being a 32-bit CPU, the ARM actually has a 4GB address space \u00e2\u20ac\u201c have a look at the documentation for the specifics.<\/p>\n<p>A quick aside to talk about how the device is actually programmed. The two jumpers that we had to ensure were connected pass two of the pins through the USB part of the Discovery board (SWDIO on PA13, and SWDCLK on PA14). Those pins are set on reset to use the SWD mode as their alternate function. It probably isn\u00e2\u20ac\u2122t wise, while using the DISCOVERY board to change away from that, as you won\u00e2\u20ac\u2122t be able to debug. If you want those pins for your own application, you may also have to take the jumpers off after programming.<\/p>\n<p>Inconveniently, <code>USART1<\/code> (as PA9 and PA10) are connected to the USB-interface chip as <code>STLINK_RX<\/code> and <code>STLINK_TX<\/code>, but there is no USB serial port implemented on that interface device. The MSP430 Launchpad has the slight advantage here, the USB part also appears as a USB serial port, and those pins are connected to the device, so you have a ready made debug serial port to communicate with the device \u00e2\u20ac\u201c no such luck on Discovery, you\u00e2\u20ac\u2122ll have to get a USB-TTL serial converter (but they\u00e2\u20ac\u2122re only a couple of pounds on eBay, and no embedded programmer should be without one anyway) then connect to JP1 (after adding solderbridges SB14 and SB15).<\/p>\n<h2 id=\"toolchain\">Toolchain<\/h2>\n<p>Before we can compile our own programs, we\u00e2\u20ac\u2122re going to need a compiler.<\/p>\n<p>You\u00e2\u20ac\u2122ll want the bare-metal version of the toolchain, <code>arm-none-eabi<\/code>. Code Sourcery (now Mentor Graphics) <a href=\"http:\/\/www.mentor.com\/embedded-software\/sourcery-tools\/sourcery-codebench\/editions\/lite-edition\/\">distribute<\/a> a convenient set of builds for the ARM cross-compiler and toolchain. I believe it will be possible, with a bit of research, to use the <code>arm-linux-eabi<\/code> version, and hence to get the cross-compiler direct from the <em>emdebian<\/em> project. For now though, fill in the annoying \u00e2\u20ac\u0153what\u00e2\u20ac\u2122s your name\u00e2\u20ac\u009d form and download the bare-metal compiler from Mentor.<\/p>\n<p>I keep mine in <code>\/opt\/<\/code>:<\/p>\n<pre><code>$ cd \/opt\n$ sudo tar axvf \/home\/user\/download\/arm-2012.09-63-arm-none-eabi-i686-pc-linux-gnu.tar.bz2<\/code><\/pre>\n<p>My own habit is not to add anything to the path; it\u00e2\u20ac\u2122s easy enough to specify a toolchain prefix in most makefiles, and none of the tools themselves rely on an absolute path, or on being in the system search path, so why bother? Of course, you are welcome to do as you please.<\/p>\n<h2 id=\"compiling\">Compiling<\/h2>\n<p>Finally, we can start programming. ARM devices are considerably more complicated that the little 8-bit devices I\u00e2\u20ac\u2122ve talked about in the past. This is exacerbated by ARM not actually being a CPU, but rather being a CPU core that other manufacturers customise. This means that no two ARM-based CPUs are the same. That complexity is revealed in three key areas:<\/p>\n<ul>\n<li>We will need a customised linker script<\/li>\n<li>We will need customised startup code<\/li>\n<li>There is no standardised peripheral model (although ARM I\/O and peripheral configuration is almost universally memory mapped, meaning we will just need the magic addresses and register descriptions from the reference manual).<\/li>\n<\/ul>\n<p>We can get ourselves a start because a kind soul has already prepared a reasonable starting template, and published it as open source on <a href=\"https:\/\/github.com\/szczys\/stm32f0-discovery-basic-template\">github<\/a>.<\/p>\n<pre><code>$ cd discovery\n$ git clone https:\/\/github.com\/szczys\/stm32f0-discovery-basic-template.git<\/code><\/pre>\n<p>We\u00e2\u20ac\u2122ll being by building this minimal project simply as it is. Edit the top-level <code>Makefile<\/code> to point at your cross-compiler. Similarly the <code>Libraries\/Makefile<\/code>. Here\u00e2\u20ac\u2122s my diff:<\/p>\n<pre><code>diff --git a\/Libraries\/Makefile b\/Libraries\/Makefile\nindex 045985a..b7c9eb3 100755\n--- a\/Libraries\/Makefile\n+++ b\/Libraries\/Makefile\n@@ -1,5 +1,6 @@\n-CC=arm-none-eabi-gcc\n-AR=arm-none-eabi-ar\n+BINUTILSPREFIX=\/opt\/arm-2012.09\/bin\/arm-none-eabi-\n+CC=$(BINUTILSPREFIX)gcc\n+AR=$(BINUTILSPREFIX)ar\n \n ###########################################\n \ndiff --git a\/Makefile b\/Makefile\nindex 15ea40b..6ef995f 100755\n--- a\/Makefile\n+++ b\/Makefile\n@@ -20,10 +20,11 @@ OPENOCD_PROC_FILE=extra\/stm32f0-openocd.cfg\n \n ###################################################\n \n-CC=arm-none-eabi-gcc\n-OBJCOPY=arm-none-eabi-objcopy\n-OBJDUMP=arm-none-eabi-objdump\n-SIZE=arm-none-eabi-size\n+BINUTILSPREFIX=\/opt\/arm-2012.09\/bin\/arm-none-eabi-\n+CC=$(BINUTILSPREFIX)gcc\n+OBJCOPY=$(BINUTILSPREFIX)objcopy\n+OBJDUMP=$(BINUTILSPREFIX)objdump\n+SIZE=$(BINUTILSPREFIX)size\n \n CFLAGS  = -Wall -g -std=c99 -Os  \n #CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m0 -march=armv6s-m<\/code><\/pre>\n<p>Then build the sample project (which is in <code>src\/main.c<\/code> and <code>src\/system_stm32f0xx.c<\/code>)<\/p>\n<pre><code>$ make\n   ... deleted for brevity ...\n\/opt\/arm-2012.09\/bin\/arm-none-eabi-size main.elf\n   text    data     bss     dec     hex filename\n    856       4       4     864     360 main.elf\n$ ls -l main.bin\n-rwxrwxr-x 1 andyp andyp   860 Mar  8 18:41 main.bin<\/code><\/pre>\n<p>You can have a look at the assembler output in <code>main.lst<\/code> should you be interested, it\u00e2\u20ac\u2122s not long and helps familiarise you with the chip. Particularly useful is the symbol table included at the beginning. Here\u00e2\u20ac\u2122s some highlights:<\/p>\n<pre><code>08000000 l    d  .isr_vector    00000000 .isr_vector\n20000000 l    d  .data          00000000 .data\n20000004 l    d  .bss           00000000 .bss\nf108f85f l       *ABS*          00000000 BootRAM<\/code><\/pre>\n<p>We learn that the interrupt vectors are stored at 0x8000000 (although remember that when <code>BOOT0<\/code> is zero, 0x8000000 will be mapped to 0x00000000). The reference manual (section 11.1.3) gives us the interrupt vector table definition; but we\u00e2\u20ac\u2122ll expect the compiler and linker to take care of that for us.<\/p>\n<p>Speaking of which, you\u00e2\u20ac\u2122ll find the sample linker scripts in <code>Device\/ldscripts<\/code>, and some startup code in <code>Device\/startup_stm32f0xx.s<\/code>. If we had nothing else from this published repository, these would be enough to get us started. Linker scripts are a little arcane to read, but you can probably get the gist fairly quickly. Broadly, the three scripts relate as follows:<\/p>\n<dl>\n<dt><code>sections_flash.ld<\/code><\/dt>\n<dd>\n<p>This lists the common elf sections that all C programs use (and a few extras). It positions them relative to each other but symbolically in the memory map (it uses <code>FLASH<\/code> and <code>RAM<\/code> as the symbolic names for those absolute memory sections).<\/p>\n<\/dd>\n<dt><code>stm32f0discovery_def.ld<\/code><\/dt>\n<dd>\n<p>This puts numbers on <code>FLASH<\/code> and <code>RAM<\/code> and sets their sizes, it also sets the top of the stack (<code>_estack<\/code>). Importantly it also defines the entry point as being the symbol <code>Reset_Handler<\/code>.<\/p>\n<\/dd>\n<dt><code>stm32f0.ld<\/code><\/dt>\n<dd>\n<p>This file defines nothing and simply includes the other two. The linker should be told to use this script alone.<\/p>\n<\/dd>\n<\/dl>\n<p>Personally, I think the three files are incorrectly named (there is nothing specific to the discovery board for example), but their contents is sound.<\/p>\n<p>The startup code is ST\u00e2\u20ac\u2122s own file, and is mostly just loops to initialise <code>.bss<\/code> and <code>.data<\/code>. The more important parts are these:<\/p>\n<pre><code>Reset_Handler:\n  ldr   r0, =_estack\n  mov   sp, r0          \/* set stack pointer *\/<\/code><\/pre>\n<p>This is pretty standard; the very first thing you ever do is initialise the stack. It\u00e2\u20ac\u2122s done symbolically to the number that was set in <code>stdm32f0discovery_def.ld<\/code>, 0x20002000, the top of RAM.<\/p>\n<pre><code>\/* Call the clock system intitialization function.*\/\n    bl  SystemInit\n\/* Call static constructors *\/\n    bl __libc_init_array\n\/* Call the application&#39;s entry point.*\/\n  bl main<\/code><\/pre>\n<p><code>__libc_init_array<\/code> won\u00e2\u20ac\u2122t be doing anything important (for the CPU, it\u00e2\u20ac\u2122ll be important for your program), so <code>SystemInit<\/code> is were it\u00e2\u20ac\u2122s all happening.<\/p>\n<p>I won\u00e2\u20ac\u2122t go through it here (it\u00e2\u20ac\u2122s not very long), but you\u00e2\u20ac\u2122ll find <code>SystemInit()<\/code> as a C function in <code>Libraries\/CMSIS\/Device\/ST\/STM32F0xx\/Source\/Templates\/system_stm32f0xx.c<\/code>. This sort of code is not complicated in what it does, but is filled with magic numbers that you need will need the reference manual to interpret. Primarily it\u00e2\u20ac\u2122s configuring clocks.<\/p>\n<p>Enough prevarication, let\u00e2\u20ac\u2122s burn it (there\u00e2\u20ac\u2122s actually a \u00e2\u20ac\u02dcprogram\u00e2\u20ac\u2122 recipe in the sample makefile, but we\u00e2\u20ac\u2122ll use mine:<\/p>\n<pre><code>$ make -f Makefile.ocd program BINARY=main.bin   \nopenocd \\\n                -f \/usr\/share\/openocd\/scripts\/board\/stm32f0discovery.cfg \\\n                -c &quot;init&quot; \\\n                -c &quot;reset halt&quot; \\\n                -c &quot;sleep 100&quot; \\\n                -c &quot;wait_halt 2&quot; \\\n                -c &quot;flash write_image erase main.bin 0x08000000&quot; \\\n                -c &quot;sleep 100&quot; \\\n                -c &quot;verify_image main.bin 0x08000000&quot; \\\n                -c &quot;sleep 100&quot; \\\n                -c &quot;reset halt&quot; \\\n                -c &quot;shutdown&quot;\nOpen On-Chip Debugger 0.6.1 (2012-12-06-12:40)\nLicensed under GNU GPL v2\nFor bug reports, read\n        http:\/\/openocd.sourceforge.net\/doc\/doxygen\/bugs.html\nadapter speed: 1000 kHz\nsrst_only separate srst_nogate srst_open_drain\nInfo : clock speed 1000 kHz\nInfo : stm32f0x.cpu: hardware has 4 breakpoints, 2 watchpoints\ntarget state: halted\ntarget halted due to debug-request, current mode: Thread \nxPSR: 0xc1000000 pc: 0x080002ec msp: 0x20002000\nauto erase enabled\nInfo : device id = 0x20006440\nInfo : flash size = 64kbytes\ntarget state: halted\ntarget halted due to breakpoint, current mode: Thread \nxPSR: 0x61000000 pc: 0x2000003a msp: 0x20002000\nwrote 1024 bytes from file basic-template.bin in 0.113688s (8.796 KiB\/s)\ntarget state: halted\ntarget halted due to breakpoint, current mode: Thread \nxPSR: 0x61000000 pc: 0x2000002e msp: 0x20002000\nverified 860 bytes in 0.033818s (24.834 KiB\/s)\ntarget state: halted\ntarget halted due to debug-request, current mode: Thread \nxPSR: 0xc1000000 pc: 0x080002ec msp: 0x20002000\nshutdown command invoked<\/code><\/pre>\n<p>For some reason the chip needs a power cycle after you\u00e2\u20ac\u2122ve done this (perhaps I\u00e2\u20ac\u2122m missing a command in the OpenOCD script), which you can do by removing and re-attaching JP2 (pushing reset isn\u00e2\u20ac\u2122t enough). The blue LED should start flashing.<\/p>\n<p>Done.<\/p>\n<p>There is more to say about actually writing code this device, but that will be for another day, much of what I\u00e2\u20ac\u2122ve said in other embedded articles is entirely relevant (programming is all the same in the end).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction I\u00e2\u20ac\u2122ve added another nice cheap dev board to my collection, the STM32F0 Discovery, which I got from RS in the UK for \u00c2\u00a3. It\u00e2\u20ac\u2122s an SGS Thompson (ST) kit, based around their STMF051R8T6 device, which is in turn based on an Arm Cortex M0. I like this sort of dev board so much because\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.fussylogic.co.uk\/blog\/?p=994\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[67,68,37,42,6],"_links":{"self":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/994"}],"collection":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=994"}],"version-history":[{"count":10,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/994\/revisions"}],"predecessor-version":[{"id":1332,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/994\/revisions\/1332"}],"wp:attachment":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=994"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=994"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=994"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}