I finally succeeded in doing what I set out to do: Write a simple hello world program for an ARM Cortex-M processor using ONLY D.

/*************************
* The D Program (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);
  }
}

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

Tools used:
Operating System: Arch Linux 64-bit
Compiler:  LDC (2063b4)
Linker & Binary Utilities & Debugger: GNU Tools for ARM Embedded Processors (https://launchpad.net/gcc-arm-embedded)
JTAG Emulator: JTAG-lock-pick Tiny 2 w/ OpenOCD 0.7.0

To compile:
ldc2 -march=thumb -mcpu=cortex-m4 -noruntime -nodefaultlib -c start.d

To link:
arm-none-eabi-ld -T link.ld --gc-sections start.o -o start.elf

To execute:
openocd -f interface/jtag-lock-pick_tiny_2.cfg -f target/stm32f4x.cfg
arm-none-eabi-gdb start.elf

.. in GDB:
target remote localhost:3333
monitor arm semihosting enable
monitor reset halt
load
monitor reset init
continue

Output:
hello
hello
...

Code Size: 148 bytes (not bad)

Why I think this is significant:
1. It shows D can write the most low level of programs and does not require an operating system 2. It shows that the D runtime and D standard library are not mandatory and do not need to be fully ported to one's platform to begin programming ARM Cortex-M bare metal hardware in D (although this is not the first to do so: https://bitbucket.org/timosi/minlibd)
3.  It shows linking to C code and assembly files are optional
4. It shows the tools are capable (although they have not been well exercised in this example) and more specifically MY toolchain is working. 5. It's a great start to writing very embedded systems in D, or more importantly, not C/C++ (good riddance!)

What's next for me:
1. Get a GDC toolchain working, although I'll probably switch to LDC when LDC matures.
2. Learn more about D.
3. Study minlibd and the d runtime and program the bare essentials to make D a productive language for the ARM Cortex-M. 4. Help the D community help me, by testing the toolchains for the ARM Cortex-M platform and file bug reports.

Thanks to those who commented on my previous posts. I'm quite excited about this language.

Reply via email to