digitalmars.D - Need help making minimal bare metal ARM Cortex-M D program
- Mike (68/68) Nov 24 2013 I am very new to D, but I finally got my toolchain compiled and
- David Nadlinger (5/7) Nov 24 2013 There isn't right now, but it would be entirely feasible to
- Mike (3/10) Nov 24 2013 https://github.com/ldc-developers/ldc/issues/547
- Timo Sintonen (6/18) Nov 24 2013 A full working example for gdc and cortex-m4 (stm32f4) is in my
- Mike (37/42) Nov 24 2013 Thanks Timo, your minlibd is awesome, and will be my next object
- Mike (115/115) Nov 30 2013 I finally succeeded in doing what I set out to do: Write a
- Iain Buclaw (20/118) Nov 30 2013 Processors (https://launchpad.net/gcc-arm-embedded)
- Timo Sintonen (6/16) Nov 30 2013 Congratulations from me too.
- David Nadlinger (7/10) Dec 01 2013 That's some nice progress indeed!
- Mike (1/6) Dec 02 2013 http://wiki.dlang.org/Extremely_minimal_semihosted_%22Hello_World%22
- David Nadlinger (4/5) Dec 02 2013 Thanks a lot, Mike!
I am very new to D, but I finally got my toolchain compiled and working. I'm using LDC. I failed with GDC and eventually gave up. I am trying to get an _extremely_ minimal bare metal ARM Cortex-M HelloWorld-type program (no phobos, no runtime, nothing but what I type myself) compiled and executed on my STM32F4-based hardware. I know the toolchain is buggy for arm right now, but I'm hoping I can do something about that if I can just get started. Here's the basic C code and linker script for my hardware. It doesn't actually print "hello world". I intend to add that after I get the following code compiled and downloaded to my hardware. /*************************** * start.c ****************************/ // defined in linker script extern unsigned long _stack_end; void handler_reset(void) { //Print hello world using SWI } __attribute__ ((section(".interrupt_vector"))) void (* const table_interrupt_vector[])(void) = { (void *) &_stack_end, handler_reset }; /*************************** * linkerscript.ld ****************************/ MEMORY { CCRAM (rxw) : ORIGIN = 0x10000000, LENGTH = 64k SRAM (rxw) : ORIGIN = 0x20000000, LENGTH = 128k FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024k } _stack_end = ORIGIN(CCRAM) + LENGTH(CCRAM); SECTIONS { .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) . = ALIGN(4); } >FLASH .text : { . = ALIGN(4); KEEP(*(.interrupt_vector)) *(.text) *(.text*) *(.rodata) *(.rodata*) . = ALIGN(4); } > flash } Can anyone out them tell me if/how this can be accomplished in D? Is there some syntax equivalent to __attribute__ ((section(".interrupt_vector")))? Would the following give me a minimal reset_handler? // compile with: ldc2 -c -nodefaultlib -noruntime module reset_handler; extern(C) __gshared void * _Dmodule_ref; extern(C) void reset_handler() { } I've seen some examples out on the web, but they all either use C, or are written specifically for an x86/x86_64 platform. So any help you could provide would be great to help me get started.
Nov 24 2013
On Sunday, 24 November 2013 at 13:00:39 UTC, Mike wrote:Is there some syntax equivalent to __attribute__ ((section(".interrupt_vector")))?There isn't right now, but it would be entirely feasible to implement this in an LDC-specific extension. Could you open an issue on our GitHub tracker? David
Nov 24 2013
On Sunday, 24 November 2013 at 13:30:10 UTC, David Nadlinger wrote:On Sunday, 24 November 2013 at 13:00:39 UTC, Mike wrote:https://github.com/ldc-developers/ldc/issues/547Is there some syntax equivalent to __attribute__ ((section(".interrupt_vector")))?There isn't right now, but it would be entirely feasible to implement this in an LDC-specific extension. Could you open an issue on our GitHub tracker? David
Nov 24 2013
On Sunday, 24 November 2013 at 14:10:54 UTC, Mike wrote:On Sunday, 24 November 2013 at 13:30:10 UTC, David Nadlinger wrote:A full working example for gdc and cortex-m4 (stm32f4) is in my repo at https://bitbucket.org/timosi/minlibd I have used startup file from st and have no need to put interrupt vectors in d code.On Sunday, 24 November 2013 at 13:00:39 UTC, Mike wrote:https://github.com/ldc-developers/ldc/issues/547Is there some syntax equivalent to __attribute__ ((section(".interrupt_vector")))?There isn't right now, but it would be entirely feasible to implement this in an LDC-specific extension. Could you open an issue on our GitHub tracker? David
Nov 24 2013
On Sunday, 24 November 2013 at 20:00:56 UTC, Timo Sintonen wrote:A full working example for gdc and cortex-m4 (stm32f4) is in my repo at https://bitbucket.org/timosi/minlibd I have used startup file from st and have no need to put interrupt vectors in d code.Thanks Timo, your minlibd is awesome, and will be my next object of study. I already know how do do what you did with assembly and C, but my goal is not just to get something working, but to learn what can and can't be done with D. minlibd uses an assembly startup file and calls into C functions to set up the clock, flash, etc... That works, and may be the only (best?) way to go. But I'd like to explore and learn what limitations exist in the D language and the D tools. If the LDC folks add a section-attribute-like feature, then I believe it should be possible to do away with the assembly startup file, and put the vectors, data section relocation, and bss initialization all in D, and that appeals to me. I'm wondering, though, if the vector table's simple name could be added to the text section. Then the attribute syntax would be unnecessary. Something like this: void (* const table_interrupt_vector[])(void) = { (void *) &_stack_end, handler_reset }; .text : { . = ALIGN(4); *(.text.table_interrupt_vector) *(.text) *(.text*) *(.rodata) *(.rodata*) . = ALIGN(4); } > flash ...but maybe the symbol will be added twice. Unfortunately I won't be home for a few more days to try it out. According to LDs docs, execution should default to the start of text, and if I could just figure out how to make sure table_interrrupt_vector is there, that would basically be it.
Nov 24 2013
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; "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.
Nov 30 2013
On Nov 30, 2013 11:40 AM, "Mike" <none none.com> wrote:I finally succeeded in doing what I set out to do: Write a simple helloworld 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; "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 EmbeddedProcessors (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 notrequire an operating system2. It shows that the D runtime and D standard library are not mandatoryand 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 wellexercised in this example) and more specifically MY toolchain is working.5. It's a great start to writing very embedded systems in D, or moreimportantly, not C/C++ (good riddance!)What's next for me: 1. Get a GDC toolchain working, although I'll probably switch to LDC whenLDC matures.2. Learn more about D. 3. Study minlibd and the d runtime and program the bare essentials tomake D a productive language for the ARM Cortex-M.4. Help the D community help me, by testing the toolchains for the ARMCortex-M platform and file bug reports.Thanks to those who commented on my previous posts. I'm quite excitedabout this language. In before the "that's not D! That's some D, a bit of some extended inline assembly, and a custom linker script." Congrats though. :) Regards -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Nov 30 2013
On Saturday, 30 November 2013 at 11:37:25 UTC, Mike wrote: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.Congratulations from me too. I just put my old gdc cross compiler instructions in the wiki: https://bitbucket.org/timosi/minlibd/wiki/gdc_cross_compiler If you are not going to have your own repository, feel free to send pull requests to me.
Nov 30 2013
On Saturday, 30 November 2013 at 11:37:25 UTC, Mike wrote: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.That's some nice progress indeed! Would you mind transferring your excellent description of the process to the D wiki and link it from http://wiki.dlang.org/LDC? This way, it would be easier to find in a few months than an old forum post. David
Dec 01 2013
Would you mind transferring your excellent description of the process to the D wiki and link it from http://wiki.dlang.org/LDC? This way, it would be easier to find in a few months than an old forum post. Davidhttp://wiki.dlang.org/Extremely_minimal_semihosted_%22Hello_World%22
Dec 02 2013
On Monday, 2 December 2013 at 11:09:15 UTC, Mike wrote:http://wiki.dlang.org/Extremely_minimal_semihosted_%22Hello_World%22Thanks a lot, Mike! I linked the page from the LDC platform overview. David
Dec 02 2013