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

From D Wiki
Jump to: navigation, search
(Program Source Code (start.d))
(The Code)
Line 15: Line 15:
 
* (JTAG emulator) [http://www.distortec.com/jtag-lock-pick-tiny-2 JTAG-lock-pick Tiny 2]
 
* (JTAG emulator) [http://www.distortec.com/jtag-lock-pick-tiny-2 JTAG-lock-pick Tiny 2]
  
=The Code=
+
=The Code (LDC)=
 
==Program Source Code (start.d)==
 
==Program Source Code (start.d)==
 
<syntaxhighlight lang="D">
 
<syntaxhighlight lang="D">

Revision as of 11:21, 21 December 2013

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

Goals

  • 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

Tools

The Code (LDC)

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 -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.

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))     /* Interrupt 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
  • 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