Difference between revisions of "Minimal semihosted ARM Cortex-M "Hello World""

From D Wiki
Jump to: navigation, search
(Linker Script(link.ld))
(Linker Script (link.ld))
Line 80: Line 80:
     LONG(_stackStart);              /* Initial stack pointer */
     LONG(_stackStart);              /* Initial stack pointer */
     KEEP(start.o(.data.rel.ro))    /* Internet vector table */
     KEEP(start.o(.data.rel.ro))    /* Interrupt vector table */
     /* the code */
     /* the code */

Revision as of 03:40, 3 December 2013

The following is an extremely minimal, semihosted "Hello World" D program for ARM Cortex-M processors.


  • Verify the 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


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)
    "mov r0, $0;
     mov r1, $1;
     bkpt #0xAB",
     command, message

void OnReset()
    // 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

You will have to change the -mcpu option for your processor accordingly (e.g. cortex-m0, cortex-m3, etc...)

Linker Script (link.ld)

NOTE: This linker script was written specifically for an STM32F4 MCU. The MEMORY section and _stackStart will have to be tailored to your hardware.

  CCRAM    (rxw) : ORIGIN = 0x10000000, LENGTH =   64k
  SRAM     (rxw) : ORIGIN = 0x20000000, LENGTH =  128k
  FLASH    (rx)  : ORIGIN = 0x08000000, LENGTH = 1024k


  .text :
    LONG(_stackStart);              /* Initial stack pointer */
    KEEP(start.o(.data.rel.ro))     /* Interrupt vector table */

    /* the code */

    /* for "hello\r\n" string constant */
    . = ALIGN(4);

  /* 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


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
monitor reset init

Output (in OpenOCD window):



  • Modify this software to compile for both GDC and LDC
  • Modify software to include data and bss sections and initialize them in the reset handler (Part 2?)
  • Begin porting the D Runtime to the ARM Cortex-M platform