Working LED blinker!
authorethereal <ethereal@ethv.net>
Tue, 11 Mar 2014 04:20:44 +0000 (22:20 -0600)
committerethereal <ethereal@ethv.net>
Tue, 11 Mar 2014 04:20:44 +0000 (22:20 -0600)
vm/.gitignore [new file with mode: 0644]
vm/Makefile [new file with mode: 0644]
vm/src/interrupt.h [new file with mode: 0644]
vm/src/sam3n.ld [new file with mode: 0644]
vm/src/startup.c [new file with mode: 0644]

diff --git a/vm/.gitignore b/vm/.gitignore
new file mode 100644 (file)
index 0000000..ce74ea9
--- /dev/null
@@ -0,0 +1,3 @@
+vm.bin
+vm.elf
+/obj
diff --git a/vm/Makefile b/vm/Makefile
new file mode 100644 (file)
index 0000000..9ba025c
--- /dev/null
@@ -0,0 +1,43 @@
+C_SOURCES=$(wildcard src/*.c)
+OBJECTS=$(patsubst src/%,obj/%,$(C_SOURCES:.c=.o))
+OBJECT_DIRECTORY=obj
+
+COMPILER_PREFIX=arm-none-eabi-
+
+CC=$(COMPILER_PREFIX)gcc
+LD=$(COMPILER_PREFIX)ld
+OBJCOPY=$(COMPILER_PREFIX)objcopy
+
+EXEC=vm
+
+LOCAL_CFLAGS=-std=c11 -Wextra -Wall -Wno-unused-parameter -ffreestanding -nostdlib
+LOCAL_LDFLAGS=-nostdlib -T src/sam3n.ld
+
+CFLAGS=$(LOCAL_CFLAGS)
+LDFLAGS=$(LOCAL_LDFLAGS)
+
+all: $(EXEC).bin
+
+.PHONY: redep
+redep:
+       $(CC) $(CFLAGS) -MM $(C_SOURCES) > depend
+-include depend
+
+$(OBJECT_DIRECTORY):
+       @mkdir -p $(OBJECT_DIRECTORY)
+
+obj/%.o: src/%.c
+       $(CC) $(CFLAGS) -c $< -o $@
+
+$(OBJECTS): | $(OBJECT_DIRECTORY)
+
+$(EXEC).elf: $(OBJECTS)
+       $(LD) $(LDFLAGS) $(OBJECTS) -o $(EXEC).elf
+
+$(EXEC).bin: $(EXEC).elf
+       $(OBJCOPY) $(EXEC).elf -O binary $(EXEC).bin
+
+.PHONY: clean
+clean:
+       rm -f $(EXEC) $(OBJECTS)
+
diff --git a/vm/src/interrupt.h b/vm/src/interrupt.h
new file mode 100644 (file)
index 0000000..004314c
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef INTERRUPT_H
+#define INTERRUPT_H
+
+#include <stdint.h>
+
+typedef void (*interrupt_function_t)(void);
+
+#endif
diff --git a/vm/src/sam3n.ld b/vm/src/sam3n.ld
new file mode 100644 (file)
index 0000000..34298f2
--- /dev/null
@@ -0,0 +1,114 @@
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")\r
+OUTPUT_ARCH(arm)\r
+SEARCH_DIR(.)\r
+\r
+/* Memory Spaces Definitions */\r
+MEMORY\r
+{\r
+       rom (rx)  : ORIGIN = 0x00400000, LENGTH = 0x00020000 /* flash, 128K */\r
+       ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00002000 /* sram, 8K */\r
+}\r
+\r
+/* The stack size used by the application. NOTE: you need to adjust  */\r
+__stack_size__ = DEFINED(__stack_size__) ? __stack_size__ : 0x800;\r
+__ram_end__ = ORIGIN(ram) + LENGTH(ram) - 4;\r
+\r
+/* Section Definitions */\r
+SECTIONS\r
+{\r
+    .text :\r
+    {\r
+        . = ALIGN(4);\r
+        _sfixed = .;\r
+        KEEP(*(.vectors .vectors.*))\r
+        *(.text .text.* .gnu.linkonce.t.*)     \r
+        *(.glue_7t) *(.glue_7)         \r
+        *(.rodata .rodata* .gnu.linkonce.r.*)                  \r
+        *(.ARM.extab* .gnu.linkonce.armextab.*)\r
+\r
+        /* Support C constructors, and C destructors in both user code\r
+           and the C library. This also provides support for C++ code. */\r
+        . = ALIGN(4);\r
+        KEEP(*(.init))\r
+        . = ALIGN(4);\r
+        __preinit_array_start = .;\r
+        KEEP (*(.preinit_array))\r
+        __preinit_array_end = .;\r
+\r
+        . = ALIGN(4);\r
+        __init_array_start = .;\r
+        KEEP (*(SORT(.init_array.*)))\r
+        KEEP (*(.init_array))\r
+        __init_array_end = .;\r
+\r
+        . = ALIGN(0x4);\r
+        KEEP (*crtbegin.o(.ctors))\r
+        KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))\r
+        KEEP (*(SORT(.ctors.*)))\r
+        KEEP (*crtend.o(.ctors))\r
+\r
+        . = ALIGN(4);\r
+        KEEP(*(.fini))\r
+\r
+        . = ALIGN(4);\r
+        __fini_array_start = .;\r
+        KEEP (*(.fini_array))\r
+        KEEP (*(SORT(.fini_array.*)))\r
+        __fini_array_end = .;\r
+\r
+        KEEP (*crtbegin.o(.dtors))\r
+        KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))\r
+        KEEP (*(SORT(.dtors.*)))\r
+        KEEP (*crtend.o(.dtors))\r
+\r
+        . = ALIGN(4);\r
+        _efixed = .;            /* End of text section */\r
+    } > rom\r
+\r
+    /* .ARM.exidx is sorted, so has to go in its own output section.  */\r
+    PROVIDE_HIDDEN (__exidx_start = .);\r
+    .ARM.exidx :\r
+    {\r
+      *(.ARM.exidx* .gnu.linkonce.armexidx.*)\r
+    } > rom\r
+    PROVIDE_HIDDEN (__exidx_end = .);\r
+\r
+    . = ALIGN(4);\r
+    _etext = .;\r
+\r
+    .relocate : AT (_etext)\r
+    {\r
+        . = ALIGN(4);\r
+        _srelocate = .;\r
+        *(.ramfunc .ramfunc.*);\r
+        *(.data .data.*);\r
+        . = ALIGN(4);\r
+        _erelocate = .;\r
+    } > ram\r
+\r
+    /* .bss section which is used for uninitialized data */\r
+    .bss (NOLOAD) :\r
+    {\r
+        . = ALIGN(4);\r
+        _sbss = . ;\r
+        _szero = .;\r
+        *(.bss .bss.*)\r
+        *(COMMON)\r
+        . = ALIGN(4);\r
+        _ebss = . ;\r
+        _ezero = .;\r
+    } > ram\r
+\r
+    /* stack section */\r
+    .stack (NOLOAD):\r
+    {\r
+        . = ALIGN(8);\r
+           _sstack = .;\r
+        . = . + __stack_size__;\r
+        . = ALIGN(8);\r
+        _estack = .;\r
+    } > ram\r
+\r
+    . = ALIGN(4);\r
+    _end = . ;\r
+}\r
diff --git a/vm/src/startup.c b/vm/src/startup.c
new file mode 100644 (file)
index 0000000..e485149
--- /dev/null
@@ -0,0 +1,107 @@
+#include "interrupt.h"
+
+/* Segment symbols */
+extern uint32_t _sfixed;
+extern uint32_t _efixed;
+extern uint32_t _etext;
+extern uint32_t _srelocate;
+extern uint32_t _erelocate;
+extern uint32_t _szero;
+extern uint32_t _ezero;
+extern uint32_t _sstack;
+extern uint32_t _estack;
+
+static void startup_dummy_handler(void);
+static void startup_reset_handler(void);
+
+__attribute__ ((section(".vectors")))
+interrupt_function_t exception_table[] = {
+    (interrupt_function_t) (&_estack),
+    startup_reset_handler,
+
+    startup_dummy_handler, /* NMI */
+    startup_dummy_handler, /* Hardfault */
+    startup_dummy_handler, /* memmanage */
+    startup_dummy_handler, /* busfault */
+    startup_dummy_handler, /* usagefault */
+    0, 0, 0, 0, /* reserved */
+    startup_dummy_handler, /* svc */
+    startup_dummy_handler, /* debugmon */
+    0, /* reserved */
+    startup_dummy_handler, /* pendsv */
+    startup_dummy_handler, /* systick */
+    
+    /* configurable */
+    startup_dummy_handler, /* 0: supply controller */
+    startup_dummy_handler, /* 1: reset controller */
+    startup_dummy_handler, /* 2: RTC */
+    startup_dummy_handler, /* 3: RTT */
+    startup_dummy_handler, /* 4: watchdog */
+    startup_dummy_handler, /* 5: PMC */
+    startup_dummy_handler, /* 6: EEFC */
+    startup_dummy_handler, /* 7: reserved */
+    startup_dummy_handler, /* 8: UART0 */
+    startup_dummy_handler, /* 9: UART1 (not present on SAM3N) */
+    startup_dummy_handler, /* 10: reserved */
+    startup_dummy_handler, /* 11: PIOA  */
+    startup_dummy_handler, /* 12: PIOB */
+    startup_dummy_handler, /* 13: PIOC */
+    startup_dummy_handler, /* 14: USART 0 */
+    startup_dummy_handler, /* 15: USART 1 */
+    startup_dummy_handler, /* 16: reserved */
+    startup_dummy_handler, /* 17: reserved */
+    startup_dummy_handler, /* 18: reserved */
+    startup_dummy_handler, /* 19: TWI 0 */
+    startup_dummy_handler, /* 20: TWI 1 */
+    startup_dummy_handler, /* 21: SPI */
+    startup_dummy_handler, /* 22: reserved */
+    startup_dummy_handler, /* 23: timer counter 0 */
+    startup_dummy_handler, /* 24: timer counter 1 */
+    startup_dummy_handler, /* 25: timer counter 2 */
+    startup_dummy_handler, /* 26: timer counter 3 */
+    startup_dummy_handler, /* 27: timer counter 4 */
+    startup_dummy_handler, /* 28: timer counter 5 */
+    startup_dummy_handler, /* 29: ADC */
+    startup_dummy_handler, /* 30: DAC */
+    startup_dummy_handler, /* 31: PWM */
+    startup_dummy_handler /* 32: not used */
+};
+
+static void startup_dummy_handler(void) {
+    /* loop forever */
+    while(1) {}
+}
+
+static void startup_reset_handler(void) {
+    /* relocation segment */
+    uint32_t *src, *dest;
+    src = &_etext;
+    dest = &_srelocate;
+
+    if(src != dest) {
+        for(; dest < &_erelocate; ) *dest++ = *src++;
+    }
+
+    /* clear the BSS */
+    for(dest = &_szero; dest < &_ezero; dest ++) {
+        *dest = 0;
+    }
+
+    /* at this point, should be all good to go... */
+
+    /* need to initialize PIOC */
+    /* TODO: not required for just outputs etc. */
+
+    /* make PA3 high */
+    *(uint32_t *)(0x400e0e00) = 0x8;
+    *(uint32_t *)(0x400e0e10) = 0x8;
+
+    while(1) {
+        *(uint32_t *)(0x400e0e30) = 0x8;
+        for(int i = 0; i < 1000000; i ++) {}
+        *(uint32_t *)(0x400e0e34) = 0x8;
+        for(int i = 0; i < 1000000; i ++) {}
+    }
+
+    while(1) {}
+}