Now that we have an original flash image that we know how to restore, it is time to start building and running our own software on the board.
When it comes to the toolchain, I started with the version provided by Manjaro, but I ran into an issue related to Newlib-Nano, which is the C library that is supposed to be used with that toolchain. After a few other tries, I was finally successful with the toolchain provided by ARM and located at GNU Tools for ARM Embedded Processors, that the arch/Manjaro packages are built on anyway. As mentioned in a previous post, the installation is not more intrusive than unpacking a compressed folder and pointing to it in my PATH
.
Led by The Definitive Guide to ARM® Cortex®-M4…, who recommended the use of linker scripts provided by ARM in their toolchain samples, I decided to start by building and running the actual samples.
To start with, I reuse the exact code structure provided by ARM in their samples. My purpose was to be able to just run make
after as few adaptations as possible. The structure is the following:
1 2 3 4 5 6 7 |
[nilo@floor arm-none-eabi]$ ls -l total 20 drwxr-xr-x 2 nilo users 4096 28.06.2014 18:01 dump/ drwxr-xr-x 2 nilo users 4096 28.06.2014 21:09 ldscripts/ drwxr-xr-x 10 nilo users 4096 28.06.2014 21:19 src/ drwxr-xr-x 2 nilo users 4096 28.06.2014 18:00 startup/ -rw-r--r-- 1 nilo users 3444 16.09.2013 04:37 readme.txt |
The dump
directory is mine. The rest is a copy/paste of the contents of ARM’s sample folder.
Under ldscripts
, I have modified the contents of the mem.ld
file to match my board:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[nilo@floor arm-none-eabi]$ cat ldscripts/mem.ld /* Linker script to configure memory regions. * Need modifying for a specific board. * FLASH.ORIGIN: starting address of flash * FLASH.LENGTH: length of flash * RAM.ORIGIN: starting address of RAM bank 0 * RAM.LENGTH: length of RAM bank 0 */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x00100000 /* 1M */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x20000 /* 128K */ } |
Since gcc.ld
(used in most samples) and nokeep.ld
had the same rows, I replaced the redundancy by some INCLUDE
commands:
1 2 3 4 5 6 7 8 9 |
[nilo@floor arm-none-eabi]$ head ldscripts/gcc.ld /* Linker script to configure memory regions. * Need modifying for a specific board. * FLASH.ORIGIN: starting address of flash * FLASH.LENGTH: length of flash * RAM.ORIGIN: starting address of RAM bank 0 * RAM.LENGTH: length of RAM bank 0 */ INCLUDE "mem.ld" |
The default processor in the samples being a Cortex-M0, I also change the processor to a Cortex-M4:
[nilo@floor arm-none-eabi]$ head src/makefile.conf
1 2 3 4 5 |
# Selecting Core CORTEX_M=4 # Use newlib-nano. To disable it, specify USE_NANO= USE_NANO=--specs=nano.specs |
And then, under the src
directory, I just ran make
.
Here for the short version:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
[nilo@floor src]$ make for d in ./multiram ./minimum ./retarget ./fpout ./semihost ./fpin ./qemu ./cpp; do make -C $d || exit 1; done make[1]: Entering directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/multiram' make[1]: 'multiram-CM4.axf' is up to date. make[1]: Leaving directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/multiram' make[1]: Entering directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/minimum' make[1]: 'minimum-CM4.axf' is up to date. make[1]: Leaving directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/minimum' make[1]: Entering directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/retarget' make[1]: 'retarget-CM4.axf' is up to date. make[1]: Leaving directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/retarget' make[1]: Entering directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/fpout' make[1]: 'fpout-CM4.axf' is up to date. make[1]: Leaving directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/fpout' make[1]: Entering directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/semihost' make[1]: 'semihost-CM4.axf' is up to date. make[1]: Leaving directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/semihost' make[1]: Entering directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/fpin' make[1]: 'fpin-CM4.axf' is up to date. make[1]: Leaving directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/fpin' make[1]: Entering directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/qemu' make[1]: 'hello-CM4.axf' is up to date. make[1]: Leaving directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/qemu' make[1]: Entering directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/cpp' make[1]: 'cpp-CM4.axf' is up to date. make[1]: Leaving directory '/home/nilo/SoftwareLocal/arm-none-eabi/src/cpp' |
The simplest of these examples being minimum
, that is the one I decided to test.
1 2 3 4 5 6 7 8 9 10 |
[nilo@floor src]$ cat minimum/minimum.c #ifndef __NO_SYSTEM_INIT void SystemInit() {} #endif void main() { for (;;); } |
Under openocd
telnet:
1 2 3 4 5 6 7 8 9 10 11 |
> flash erase_address 0x08000000 0x00100000 erased address 0x08000000 (length 1048576) in 16.957106s (60.388 KiB/s) > flash write_image minimum-CM4.axf target state: halted target halted due to breakpoint, current mode: Thread xPSR: 0x61000000 pc: 0x20000042 msp: 0xfffffffc wrote 140 bytes from file minimum-CM4.axf in 0.021153s (6.463 KiB/s) > reset halt target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x08000048 msp: 0x20020000 |
The PC and the MSP match the disassembled image:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
[nilo@floor src]$ arm-none-eabi-objdump -d minimum/minimum-CM4.axf minimum/minimum-CM4.axf: file format elf32-littlearm Disassembly of section .text: 08000000 <__isr_vector>: 8000000: 20020000 .word 0x20020000 8000004: 08000049 .word 0x08000049 8000008: 08000089 .word 0x08000089 800000c: 08000089 .word 0x08000089 8000010: 08000089 .word 0x08000089 8000014: 08000089 .word 0x08000089 8000018: 08000089 .word 0x08000089 ... 800002c: 08000089 .word 0x08000089 8000030: 08000089 .word 0x08000089 8000034: 00000000 .word 0x00000000 8000038: 08000089 .word 0x08000089 800003c: 08000089 .word 0x08000089 8000040: 08000089 .word 0x08000089 08000044 <main>: 8000044: e7fe b.n 8000044 <main> 08000046 <SystemInit>: 8000046: 4770 bx lr 08000048 <Reset_Handler>: 8000048: 490a ldr r1, [pc, #40] ; (8000074 <Reset_Handler+0x2c>) 800004a: 4a0b ldr r2, [pc, #44] ; (8000078 <Reset_Handler+0x30>) 800004c: 4b0b ldr r3, [pc, #44] ; (800007c <Reset_Handler+0x34>) 800004e: 429a cmp r2, r3 8000050: bfbe ittt lt 8000052: f851 0b04 ldrlt.w r0, [r1], #4 8000056: f842 0b04 strlt.w r0, [r2], #4 800005a: e7f8 blt.n 800004e <Reset_Handler+0x6> 800005c: 4908 ldr r1, [pc, #32] ; (8000080 <Reset_Handler+0x38>) 800005e: 4a09 ldr r2, [pc, #36] ; (8000084 <Reset_Handler+0x3c>) 8000060: 2000 movs r0, #0 8000062: 4291 cmp r1, r2 8000064: bfbc itt lt 8000066: f841 0b04 strlt.w r0, [r1], #4 800006a: e7fa blt.n 8000062 <Reset_Handler+0x1a> 800006c: f7ff ffeb bl 8000046 <SystemInit> 8000070: f7ff ffe8 bl 8000044 <main> 8000074: 0800008c .word 0x0800008c 8000078: 20000000 .word 0x20000000 800007c: 20000000 .word 0x20000000 8000080: 20000000 .word 0x20000000 8000084: 20000000 .word 0x20000000 08000088 <BusFault_Handler>: 8000088: e7fe b.n 8000088 <BusFault_Handler> 800008a: bf00 nop |
Now debugging in gdb
(openocd
still started, telnet
closed, gdb
connected instead):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
[nilo@floor minimum]$ arm-none-eabi-gdb GNU gdb (GNU Tools for ARM Embedded Processors) 7.6.0.20140529-cvs Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=i686-linux-gnu --target=arm-none-eabi". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. (gdb) file minimum-CM4.axf Reading symbols from /home/nilo/SoftwareLocal/arm-none-eabi/src/minimum/minimum-CM4.axf...(no debugging symbols found)...done. (gdb) target remote localhost:3333 Remote debugging using localhost:3333 0x08000044 in main () (gdb) break Breakpoint 1 at 0x8000044 (gdb) step Single stepping until exit from function main, which has no line number information. Breakpoint 1, 0x08000044 in main () (gdb) i r r0 0x0 0 r1 0x20000000 536870912 r2 0x20000000 536870912 r3 0x20000000 536870912 r4 0x0 0 r5 0x0 0 r6 0x0 0 r7 0x0 0 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x0 0 r12 0x0 0 sp 0x20020000 0x20020000 lr 0x8000075 134217845 pc 0x8000044 0x8000044 <main> xPSR 0x61000000 1627389952 (gdb) detach Detaching from program: /home/nilo/SoftwareLocal/arm-none-eabi/src/minimum/minimum-CM4.axf, Remote target Ending remote debugging. (gdb) quit |
I appreciate, cause I discovered just what I used to be looking for. You have ended my four day long hunt! God Bless you man. Have a nice day. Bye kefeffedkacb