From f5159013b3055c51e82a05de5984335eaf108dfe Mon Sep 17 00:00:00 2001 From: Gavan Fantom Date: Wed, 4 May 2011 00:03:28 +0000 Subject: [PATCH] Initial checkin. Basic build and runtime environment, prior to first test on actual hardware. --- Makefile | 38 ++++++++++ crt0.s | 187 +++++++++++++++++++++++++++++++++++++++++++++++ lpc2103_flash.ld | 47 ++++++++++++ main.c | 18 +++++ 4 files changed, 290 insertions(+) create mode 100644 Makefile create mode 100644 crt0.s create mode 100644 lpc2103_flash.ld create mode 100644 main.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1c403a2 --- /dev/null +++ b/Makefile @@ -0,0 +1,38 @@ +# Makefile + +NAME=quad + +OBJS=crt0.o main.o + +CFLAGS=-march=armv4t -msoft-float + +LDSCRIPT=lpc2103_flash.ld +CC=arm-elf-gcc +OBJCOPY=arm-elf-objcopy + +CLEANOBJS=$(OBJS) $(NAME).hex $(NAME).elf $(NAME).bin $(NAME).map + +all: $(NAME).bin + + +# In theory, nothing below here needs touching for as long as all of the +# sources are in a single directory. + + +.SUFFIXES: .elf .hex .bin + +$(NAME).elf: $(OBJS) + $(CC) $(CFLAGS) -nostdlib -nostartfiles -T $(LDSCRIPT) -Wl,-Map -Wl,$(NAME).map -o $(NAME).elf $(OBJS) -lgcc + +run: $(NAME).hex + $(FLASHER) -hex -term -control $(NAME).hex $(PORT) $(SPEED) $(OSC) + +.elf.hex: + $(OBJCOPY) -O ihex ${.IMPSRC} ${.TARGET} + +.hex.bin: + $(OBJCOPY) -I ihex -O binary ${.IMPSRC} ${.TARGET} + +clean: + rm -rf $(CLEANOBJS) + diff --git a/crt0.s b/crt0.s new file mode 100644 index 0000000..94c3baa --- /dev/null +++ b/crt0.s @@ -0,0 +1,187 @@ +# Runtime support + +# Configurable parameters + + # Set PLL ratios - M=4, P=2, 58.9824 MHz clock + .equ PLL_M, 4 + .equ PLL_P, 2 + + .equ FLASHCLOCKS, 3 /* 40-60MHz clock */ + .equ APB_DIVIDER, 4 /* 1, 2 or 4 */ + + .equ UND_STACK_SIZE, 0x0004 + .equ SVC_STACK_SIZE, 0x0004 + .equ ABT_STACK_SIZE, 0x0004 + .equ FIQ_STACK_SIZE, 0x0004 + .equ IRQ_STACK_SIZE, 0x0080 + .equ USR_STACK_SIZE, 0x0400 + +# Processor definitions + + .equ Mode_USR, 0x10 + .equ Mode_FIQ, 0x11 + .equ Mode_IRQ, 0x12 + .equ Mode_SVC, 0x13 + .equ Mode_ABT, 0x17 + .equ Mode_UND, 0x1b + .equ Mode_SYS, 0x1f + + .equ I_Bit, 0x80 + .equ F_Bit, 0x40 + +# Register definitions + + .equ MAM_BASE, 0xE01FC000 + .equ MAMCR, 0 + .equ MAMTIM, 4 + + .equ PLL_BASE, 0xE01FC080 + .equ PLLCON, 0x00 + .equ PLLCFG, 0x04 + .equ PLLSTAT, 0x08 + .equ PLLFEED, 0x0c + + .equ PLLCON_PLLE, (1<<0) + .equ PLLCON_PLLC, (1<<1) + .equ PLLCFG_MSEL, (0x1F<<0) + .equ PLLCFG_PSEL, (0x03<<5) + .equ PLLSTAT_PLOCK, (1<<10) + + .equ APBDIV_BASE, 0xE01FC100 + .equ APBDIV, 0 + + # True is -1 so we subtract values together. + .equ PLL_LOG_P, (0-(PLL_P>1)-(PLL_P>2)-(PLL_P>4)) + .equ PLLCFG_VAL, (PLL_M-1) | (PLL_LOG_P << 5) + + # 1 => 1, 2 => 2, 4 => 0 + .equ APB_VAL, (APB_DIVIDER & 3) + +.text +.global _startup +.func _startup +_startup: + +vectors: + b reset_handler + b undefined_handler + b swi_handler + b prefetch_abort_handler + b data_abort_handler + nop /* reserved */ + b irq_handler + b fiq_handler + + +reset_handler: + +# MAM and PLL setup + ldr r1, =MAM_BASE + ldr r2, =PLL_BASE + mov r3, #0xAA + mov r4, #0x55 + + +# Configure and Enable PLL + mov r0, #PLLCFG_VAL + str r0, [r2, #PLLCFG] + mov r0, #PLLCON_PLLE + str r0, [r2, #PLLCON] + str r3, [r2, #PLLFEED] + str r4, [r2, #PLLFEED] + +# Disable MAM until we turn on the PLL + mov r0, #0 /* MAM disabled */ + str r0, [r1, #MAMCR] + +# Wait until PLL Locked +lockwait: + ldr r0, [r2, #PLLSTAT] + ands r0, r0, #PLLSTAT_PLOCK + beq lockwait + +# Switch to PLL Clock + mov r0, #(PLLCON_PLLE | PLLCON_PLLC) + str r0, [r2, #PLLCON] + str r3, [r2, #PLLFEED] + str r4, [r2, #PLLFEED] + +# Enable MAM and set up flash timing + mov r0, #FLASHCLOCKS + str r0, [r1, #MAMTIM] + mov r0, #2 /* MAM fully enabled */ + str r0, [r1, #MAMCR] + +# Set APB divider + ldr r1, =APBDIV_BASE + mov r0, #APB_DIVIDER + str r0, [r1, #APBDIV] + +# Relocate .data section (Copy from ROM to RAM) + ldr r1, =_etext + ldr r2, =_data + ldr r3, =_edata +lrel: + cmp r2, r3 + ldrlo r0, [r1], #4 + strlo r0, [r2], #4 + blo lrel + +# Clear .bss section (Zero init) + mov r0, #0 + ldr r1, =_bss_start + ldr r2, =_bss_end +lzi: + cmp r1, r2 + strlo r0, [r1], #4 + blo lzi + +# Set up stacks + ldr r0, =_stack_end + + msr CPSR_c, #Mode_UND|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #UND_STACK_SIZE + + msr CPSR_c, #Mode_ABT|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #ABT_STACK_SIZE + + msr CPSR_c, #Mode_FIQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #FIQ_STACK_SIZE + + msr CPSR_c, #Mode_IRQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #IRQ_STACK_SIZE + + msr CPSR_c, #Mode_SVC|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #SVC_STACK_SIZE + + msr CPSR_c, #Mode_USR + mov sp, r0 + +# Stack Limit (only when compiled with "-mapcs-stack-check") + sub sl, sp, #USR_STACK_SIZE + + +# Prepare to go! + mov r0, #0 + mov r1, #0 + adr lr, __back + b main + +# Undefined handlers can just spin for now +undefined_handler: +swi_handler: +prefetch_abort_handler: +data_abort_handler: +irq_handler: +fiq_handler: + +__back: + b __back + +.endfunc +.end diff --git a/lpc2103_flash.ld b/lpc2103_flash.ld new file mode 100644 index 0000000..1d49ae0 --- /dev/null +++ b/lpc2103_flash.ld @@ -0,0 +1,47 @@ +ENTRY(_startup) + +MEMORY +{ + flash : ORIGIN = 0, LENGTH = 32K + ram_isp_low(A) : ORIGIN = 0x40000040, LENGTH = 224 + ram : ORIGIN = 0x40000120, LENGTH = 7872 + ram_isp_high(A) : ORIGIN = 0x40001FE0, LENGTH = 32 +} + +_stack_end = 0x40001FDC; + +SECTIONS +{ + . = 0; + +/* startup : { *(.startup)} >flash */ + + .text : + { + *crt0.o (.text) + *(.text) + *(.rodata) + *(.rodata*) + *(.glue_7) + *(.glue_7t) + _etext = .; + } >flash + + .data : + { + _data = .; + *(.data) + _edata = .; + } >ram AT >flash + + .bss : + { + _bss_start = .; + *(.bss) + } >ram + + . = ALIGN(4); + _bss_end = . ; +} + _end = .; + diff --git a/main.c b/main.c new file mode 100644 index 0000000..097ee2d --- /dev/null +++ b/main.c @@ -0,0 +1,18 @@ + +#define U0THR (*((volatile unsigned char *) 0xE000C000)) /* UART0 transmitter holding register */ +#define U0LSR (*((volatile unsigned char *) 0xE000C014)) /* UART0 line status register */ +#define U0THRE ((U0LSR & (1<<5))) /* UART0 transmitter holding register is empty */ + +void putch(char c) { + while (!U0THRE); + U0THR = c; +} + +void putstr(char *s) { + while (*s) putch(*s++); +} + +int main(void) { + putstr("Your entire life has been a mathematical error... a mathematical error I'm about to correct!\n"); + return 0; +}