Getting started with the STM32

Hi everyone,

For my next project I want to use an ARM (going to need the clock speed) and so picked up an STM32 F103 VBT6 (LQFP100 package). I also got the ARM-USB-TINY by Olimex.

I’ve soldered it down to a quick breakout board that just brings out all the pins, and connected it up to the programmer.

After going through a few threads here I managed to get OpenOCD up and running and it appears to program the device fine. I’m using the latest svn revision of OpenOCD. My sample code is from stm_p103_blink_flash which was included with the programmer.

Programming the device:

$ openocd --version
Open On-Chip Debugger 1.0 (2008-08-25-16:53) svn:967

> halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x61000000 pc: 0x000008b2
> flash probe 0
device id = 0x20016410
flash size = 128kbytes
flash 'stm32x' found at 0x08000000
> stm32x mass_erase 0
stm32x mass erase complete
> flash write_bank 0 main.bin 0
> verify_image main.bin 0
verified 4052 bytes in 1.237543s
> reset run
JTAG device found: 0x3ba00477 (Manufacturer: 0x23b, Part: 0xba00, Version: 0x3)
JTAG device found: 0x16410041 (Manufacturer: 0x020, Part: 0x6410, Version: 0x1)
> poll
target state: running

The code is meant to flash an LED connected to PC12. However, I’ve hooked a voltmeter up to PC12 and it just shows 0.78V between PC12 and GND, with no change. An LED connected to PC12 doesn’t light up.

The ARM is completely connected to the programmer (every pin on the JTAG socket goes somewhere) and all the power pins are connected to power. BOOT0 is connected to ground.

I’m at a loss as to why the code isn’t working.

I’ve tried to find other sample code to try, but haven’t succeeded.

I also tried running ‘make’ in the example folder, but got the following error:

.compiling
arm-none-eabi-gcc -I./ -c -fno-common -O0 -g -mcpu=cortex-m3 -mthumb  main.c
make: arm-none-eabi-gcc: Command not found
make: *** [main.o] Error 127

I can’t find where I’m supposed to get arm-none-eabi-gcc from. I’ve heard mentions of arm-gcc, but can’t find this anywhere either.

If anyone could point me in the right way to get code compiling, that would be really appreciated. Some kind of website with documentation would be great too, though the datasheets from ST should cover this (right?).

Thanks

hello,

arm-none-eabi-gcc is part of the CodeSourcery toolchain, you can download a free version (just the compiler) from their web site.

You can find an STM32-GCC demo in the project linked in my signature, it could help you to create your own project setup.

regards,

Giovanni

Just a few guesses:

  1. Maybe the voltmeter is too slow to register the blinking on the pin. Try probing with an oscilloscope instead

  2. The example code was probably meant for an eval board and may rely on resources that you don’t have. For example, it may be trying to use an external crystal to drive the cpu clock. If you haven’t hooked up a crystal, it will just hang (or go to the RTC tamper ISR, maybe)

  3. Try debugging the device with OpenOCD. This will require that you have the elf file. If it wasn’t included with the programmer, you’ll have to get the compiler working. Once you have the elf file, connect with gdb and try stepping through the program

gdb

target remote localhost:3333

symbol-file main.elf

s

s

s

I’m using codesourcery’s toolchain (the free part) on linux with openocd to develop for STM32F101C6T6.

For some reason none of my posts are getting through…

Typical! Must be something in the post that I’m pasting.

Sweet, installing codesourcery got me arm-none-linux-gnueabi and a quick trip to the makefile soon got it working, so the example code now compiles!

I’m having less success compiling ChibiOS though, I got version 0.6.10 and it’s erroring here:

http://randomskk.net/u/docs/chibios_error.txt

I’ve uploaded the compiled code to the board and there’s still no activity on the LED or voltmeter. Unfortunately I don’t have a scope to hook it up to, but the voltage reads the same as every other pin on that port.

The makefile doesn’t actually generate a .elf file, I get main.bin, main.o, main.out and main.list, which are generated:

arm-none-linux-gnueabi-objcopy -Obinary main.out main.bin

arm-none-linux-gnueabi-objdump -S main.out > main.list

gdb seems happy to load symbols from them but then fails to actually debug:

(gdb) target remote localhost:3333
Remote debugging using localhost:3333
warning: Can not parse XML memory map; XML support was disabled at compile time
0xdffff5fe in ?? ()
(gdb) symbol-file main.out
Reading symbols from /home/adam/Code/ARM/STM32/STM32_Example_Olimex/projects/stm_p103_blink_flash/main.out...done.
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) s
Cannot find bounds of current function
(gdb)
Cannot find bounds of current function
(gdb)

For me, this error:

Cannot find bounds of current function

happens when I try to start gdb from a halted target. I’ve found two solutions.

  1. The best solution is to open gdb and set a break point somewhere in your setup code, before interrupts are enabled. Then use the telnet interface to ‘reset halt’. Or you can try using ‘c’ in gdb to run the target until the breakpoint.

  2. the less good solution is to use the telnet interface to ‘reset run’ and then connect gdb in medias res .

I’m trying solution number one, and breaking on “int main(void)”.

However, the same error occurs:

(gdb) symbol-file main.out
Reading symbols from /home/adam/Code/ARM/STM32/STM32_Example_Olimex/projects/stm_p103_blink_flash/main.out...done.
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) break main.c:38
Breakpoint 1 at 0x10: file main.c, line 38.
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
warning: Can not parse XML memory map; XML support was disabled at compile time
0xdffff5fe in ?? ()
(gdb) c
Continuing.
target state: halted
target halted due to breakpoint, current mode: Thread
xPSR: 0x01000000 pc: 0x00000010

Program received signal SIGTRAP, Trace/breakpoint trap.
0xdffff5fe in ?? ()
(gdb) s
Cannot find bounds of current function

Could it be that main.out doesn’t contain the data it needs? I’m not really sure which file I should be loading.

Your program counter looks weird. 0x00000010 is not a normal address. I would double check BOOT0, power, clocks, and power decoupling.

When I told gdb to break at int main(void), that’s the address it gave:

(gdb) break main.c:38 
 Breakpoint 1 at 0x10: file main.c, line 38.

The chip responds normally to openocd and has decoupling on all the power lines, all of them are connected and BOOT0 is definitely tied low.

I’ve not got an external clock so I’m not sure what to check or configure there.

The CodeSourcery package I am using gives me arm-none-eabi-gcc not arm-none-linux-gnueabi, probably you are using the version dedicated to the creation of linux executables.

This one is for embedded development: http://www.codesourcery.com/gnu_toolcha … release323

Ah! I guess I saw “GNU/Linux” and just downloaded that one. I’m getting the proper one now and will see what the result is.

I’ve got the proper compiler now, and chibiOS compiles perfectly and the demo for stm32 loads onto the board. Looking at main.c I’m not sure which pin the LED is supposed to be connected to, so I can’t tell if it’s working or not. Trying to debug with gdb still gives the same error, whether I try running the program first and then connecting or connecting while halted and then running. gdb does start the program running, but gives the same error when I try step or next.

Perhaps the error gdb gives at the start - about not being able to read the memory map - is significant, given that it only gets that once it connects to openocd? I can’t find anything about that error message online, though.

The STM32 demo works on this Olimex board:

http://www.olimex.com/dev/images/ARM/ST … 03-sch.gif

The led is on pin PC12.

You can see the whole schematic there, in order to port the demo on another board the only files to change are board.h and board.c (pin settings and initialization code).

Everything else should be portable.

BTW, by pressing the board button (on PA0) a self test is started, the output goes on the serial port with the following settings: 38400,8,N,1.

regards,

Giovanni

About openocd, this is the script I run from telnet in order to load the flash and run the code:

soft_reset_halt

wait_halt

poll

flash probe 0

stm32x mass_erase 0

flash write_bank 0 ch.bin 0

soft_reset_halt

resume

It is perfect for a quick test.

In the weekend I will try to setup Eclipse to work with the STM32, I only debugged on ARM7 cores until now, the STM32 just ran without problems so I never had to debug.

I have my LED connected to PC12, but no crystal on the board - I was planning to use the internal clock, at least for the moment, while I get started. I’m not using the Olimex board but rather a pretty simple breakout board:

http://farm4.static.flickr.com/3118/263 … 8a57f6.jpg

I just tried using your script to load the firmware, and again it loads perfectly but then the LED doesn’t light up at all. Perhaps something needs to be reconfigured to have it run off the internal clock instead of an external crystal?

Correct, the demo assumes an 8MHz external crystal, you can change the clock settings in board.h and board.c. If you don’t have a crystal you have to route HSI as PLL input (search for PLLSRC_HSI_BITS).

The STM32 is a bit complicated to setup…

I’ve tried leaving the settings as they are and hooking up a 16MHz crystal, though the wires going to the microchip are quite a bit longer than I’d normally like. However, this hasn’t caused anything to happen. I don’t know if I need to adjust something in the code for it to work at all with 16MHz or if it’l just run twice as fast.

I then tried setting HSI on and HSE off, but this didn’t seem to have any effect. I may be setting them wrong - I literally went through the settings at the bottom of board.h and changed all the HSIs to 1 and the HSEs to 0.

The 16MHz crystal should work according to the data sheet, of course you have to modify the initialization or the core would run at 144MHz, a bit out of specification :wink:

Find this code in board.h

#define PLLPRE 1

Change it in:

#define PLLPRE 2

This should divide by two the HSE clock before entering the PLL. Then change:

#define HSECLK 8000000

in

#define HSECLK 16000000

Here is the code I use to initialize my clocks. I use the HSI clock and run at 36MHz

void clock_init(){                                                                            
  /*Configure all clocks to max for best performance.                                         
   * If there are EMI, power, or noise problems, try slowing the clocks*/                     
                                                                                              
  /* First set the flash latency to work with our clock*/                                     
  /*000 Zero wait state, if 0  MHz < SYSCLK <= 24 MHz                                         
    001 One wait state, if  24 MHz < SYSCLK <= 48 MHz                                         
    010 Two wait states, if 48 MHz < SYSCLK <= 72 MHz */                                      
  FLASH_SetLatency(FLASH_Latency_1);                                                          
                                                                                              
  /* Start with HSI clock (internal 8mhz), divide by 2 and multiply by 9 to                   
   * get maximum allowed frequency: 36Mhz                                                     
   * Enable PLL, wait till it's stable, then select it as system clock*/                      
  RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);                                        
  RCC_PLLCmd(ENABLE);                                                                         
  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {}                                       
  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                                  
                                                                                              
  /* Set HCLK, PCLK1, and PCLK2 to SCLK (these are default */                                 
  RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                            
  RCC_PCLK1Config(RCC_HCLK_Div1);                                                             
  RCC_PCLK2Config(RCC_HCLK_Div1);                                                             
                                                                                              
  /* Set ADC clk to 9MHz (14MHz max, 18MHz default)*/                                         
  RCC_ADCCLKConfig(RCC_PCLK2_Div4);                                                           
                                                                                              
  /*To save power, use below functions to stop the clock to ceratin                           
   * peripherals                                                                              
   * RCC_AHBPeriphClockCmd                                                                    
   */                                                                                         
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA, ENABLE);                                           
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, ENABLE);                                         
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_ALL, ENABLE);                                         
                                                                                              
}