Minimal semihosted ARM Cortex-M "Hello World"
Revision as of 11:13, 2 December 2013 by Klickverbot (talk | contribs) (Klickverbot moved page Extremely minimal semihosted "Hello World" to Minimal semihosted ARM Cortex-M "Hello World")
The following is an extremely minimal, semihosted "Hello World" D program for ARM Cortex-M processors.
Contents
Goals
- Verify ARM Cortex-M toolchain (compiler-->linker-->debugger)
- Demonstrate that the D runtime and D standard library are not mandatory
- Demonstrate that linking to C code is not necessary
- Demonstrate that all required assembly code can be done within D
- Provide a starting point, with a low barrier to entry, for developers to begin testing the toolchain, porting the D runtime and libraries to the ARM Cortex-M platform, and programming their ARM Cortex-M software in D
Tools
- (host computer) Arch Linux 64-bit
- (compiler) LDC with ARM backend
- (linker & debugger) GNU Tools for GNU Tools for ARM Embedded Processors 4.7-2013-q3
- (GDB server) OpenOCD 0.7.0
- (JTAG emulator) JTAG-lock-pick Tiny 2
The Code
Program Source code (start.d)
module start;
import ldc.llvmasm;
extern(C) __gshared void * _Dmodule_ref;
//Must be stored as second 32-bit word in .text section
immutable void function() ResetHandler = &OnReset;
void SendCommand(int command, void* message)
{
__asm
(
"mov r0, $0;
mov r1, $1;
bkpt #0xAB",
"r,r,~{r0},~{r1}",
command, message
);
}
void OnReset()
{
while(true)
{
// Create semihosting message message
uint[3] message =
[
2, //stderr
cast(uint)"hello\r\n".ptr, //ptr to string
7 //size of string
];
//Send semihosting command
SendCommand(0x05, &message);
}
}
Compile with:
ldc2 -march=thumb -mcpu=cortex-m4 -noruntime -nodefaultlib -c start.d
Linker Script(link.ld)
MEMORY
{
CCRAM (rxw) : ORIGIN = 0x10000000, LENGTH = 64k
SRAM (rxw) : ORIGIN = 0x20000000, LENGTH = 128k
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024k
}
_stackStart = ORIGIN(CCRAM) + LENGTH(CCRAM);
SECTIONS
{
.text :
{
LONG(_stackStart); /* Initial stack pointer */
KEEP(start.o(.data.rel.ro)) /* Internet vector table */
/* the code */
*(.text)
*(.text*)
/* for "hello\r\n" string constant */
. = ALIGN(4);
*(.rodata)
*(.rodata*)
}>FLASH
/* Need .data, .bss, .ctors and probably more as program becomes
More complex */
}
Link with:
arm-none-eabi-ld -T link.ld --gc-sections start.o -o start.elf
Execution
Start OpenOCD:
openocd -f interface/jtag-lock-pick_tiny_2.cfg -f target/stm32f4x.cfg
Start GDB:
arm-none-eabi-gdb start.elf
In GDB, attach to OpenOCD, reset the hardware, load the executable, and begin execution
target remote localhost:3333
monitor arm semihosting enable
monitor reset halt
load
monitor reset init
continue
Output (in OpenOCD window):
hello
hello
...
TODO
- Modify this software to compile for both GDC and LDC