Update: This will only be needed if you're running OpenOCD from before Jan 16 2015 on Big Endian machines. The problem is fixed in later builds.
I'm not sure this applies to all STMicroelectronics STM32F4 Discovery boards, but it does to mine.
For a while, I haven't been able to flash-program the board, because my only available tool is OpenOCD; I have no other options. The reason I could not flash-program the board, is that the unlock procedure for the board in OpenOCD, does not remove write-protection in the OPTCR register.
Fortunately, this is no problem; OpenOCD is scriptable, so it's possible to make it work.
Let's assume we're running OpenOCD's server and we telnet into the server...
In our first terminal window, we start OpenOCD as a server:
$ openocd -f board/stm32f4discovery.cfg
We open a second terminal window and telnet into the OpenOCD server:
$ telnet localhost 4444
Start by issuing a halt command; this will stop program-execution on the discovery board.
We can either issue a 'halt' or a 'reset halt'; In this example I use 'reset halt':
halt
reset halt'
'reset halt'
> reset halt
Next, let's use the official unlock procedure that ships with OpenOCD:
> stm32f2x unlock 0
We will also need to unlock the OPTCR register. This is done by writing a special sequence of data into the OPTKEYR register.
Right after unlocking it, we want to change the value of the OPTCR register:
> mww 0x40023C08 0x08192A3B; mww 0x40023C08 0x4C5D6E7F; mww 0x40023C14 0x0fffaaed
We can now flash-program the board; it is recommended to use the .elf format:
> flash write_image erase led-blinker.elf
This can all be put in a script; For instance, my script resembles the following:
# file: my_stm32f4.cfg proc myUnlock () { stm32f2x unlock 0 mww 0x40023C08 0x08192A3B; mww 0x40023C08 0x4C5D6E7F mww 0x40023C14 0x0fffaaed } proc myFlash {file_to_flash} { init; sleep 200 reset halt; wait_halt myUnlock () flash write_image erase "$file_to_flash" reset run; sleep 10 shutdown } proc myRun () { init; sleep 200 reset halt; wait_halt reset run; sleep 10 shutdown }
So you can program the discovery board using the following command on the command-line:
$ openocd -f board/stm32f4discovery.cfg -f my_stm32f4.cfg -c "myFlash myFile.elf"
Special thanks go to John Frenz from the my.st.com forum, for helping me find this solution.
Update: You can actually write the OPTCR value, so it will not be changed back after a reset. Again, John Frenz pointed me in the right direction on how to do this:
> reset halt; mww 0x40023C08 0x08192A3B; mww 0x40023C08 0x4C5D6E7F; mdw 0x40023c14 > mww 0x40023C14 0x0fffaaec; sleep 200; mdw 0x40023c14; mww 0x40023C14 0x0fffaaef; sleep 200; mdw 0x40023c14; reset halt; mdw 0x40023c14
Note: In order to write the correct value, 0x0FFFAAED, it is necessary to first write the value with the low two bits cleared, then writing the value with bit 1 set will do the trick. The lock bit can also be set on the second write, but it will automatically be set after a reset anyway.
0x0FFFAAED
The 'sleep' commands are necessary, in order to avoid getting errors when reading the status register using 'mdw'.
mdw
Sometimes it's worth it to keep going and not give up.
The STM32F407 is quite advanced. I'm currently looking into how to use the timers.
As timers can be cascaded, this opens up a number of new possibilities; the timers also have good DMA possibilites.
Because of the large Flash memory and the ART-accelerator, one can benefit a lot from making constant look-up tables - they would be just as fast as if using SRAM.