$(AS) $(CFLAGS) -o start.o start.asm
$(CC) $(CFLAGS) -c -I./include -ffreestanding -o main.o main.c
$(CC) $(CFLAGS) -c -I./include -ffreestanding -o uart.o uart.c
- $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o
+ $(CC) $(CFLAGS) -c -I./include -ffreestanding -o ivt.o ivt.c
+ $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o ivt.o
$(MKIMG) -Obinary -R .data start.out kernel.bin
run:
- qemu-system-arm -serial stdio -M lm3s6965evb -kernel kernel.bin
+ qemu-system-arm -serial stdio -M lm3s6965evb -kernel kernel.bin
examine:
arm-none-eabi-objdump -S start.out
--- /dev/null
+/*
+ * Example memory map for the Cortex-A3
+ * Implementations vary among manufacturers. This one is
+ * a STM32F013RC6. Addresses of peripherals vary amongst
+ * manufacturers of boards with similar chips
+ *
+ * Peaceļ¼
+ * */
+
+/* VECTOR TABLE */
+#define NVIC_VECTTBL ((volatile unsigned long *)( 0xE000ED08))
+#define NVIC_EN0 ((volatile unsigned long *)( 0xE000E100))
+#define NVIC_EN1 ((volatile unsigned long *)( 0xE000E104))
+
+/* SYSTEM CONTROL REGISTERS */
+#define SYSCTRL_RCC ((volatile unsigned long *)(0x400FE060))
+#define SYSCTRL_RIS ((volatile unsigned long *)(0x400FE050))
+#define SYSCTRL_RCGC1 ((volatile unsigned long *)(0x400FE104))
+#define SYSCTRL_RCGC2 ((volatile unsigned long *)(0x400FE108))
+#define GPIOPA_AFSEL ((volatile unsigned long *)(0x40004420))
+
+/* USART REGISTERS */
+#define UART0_DATA ((volatile unsigned long *)(0x4000C000))
+#define UART0_FLAG ((volatile unsigned long *)(0x4000C018))
+#define UART0_IBRD ((volatile unsigned long *)(0x4000C024))
+#define UART0_FBRD ((volatile unsigned long *)(0x4000C028))
+#define UART0_LCRH ((volatile unsigned long *)(0x4000C02C))
+#define UART0_CTRL ((volatile unsigned long *)(0x4000C030))
+#define UART0_RIS ((volatile unsigned long *)(0x4000C03C))
+
+#define UART1_DATA ((volatile unsigned long *)(0x4000D000))
+#define UART1_FLAG ((volatile unsigned long *)(0x4000D018))
+#define UART1_IBRD ((volatile unsigned long *)(0x4000D024))
+#define UART1_FBRD ((volatile unsigned long *)(0x4000D028))
+#define UART1_LCRH ((volatile unsigned long *)(0x4000D02C))
+#define UART1_CTRL ((volatile unsigned long *)(0x4000D030))
+#define UART1_RIS ((volatile unsigned long *)(0x4000D03C))
extern void uart_putc(unsigned char);
extern void uart_puts(unsigned char *);
+/* IVT.C */
+extern void ivt_init();
+
#endif
--- /dev/null
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stm32.h>
+#include <mmap.h>
+
+/* TIMER, TODO: move to timer.c */
+
+
+
+/* Interrupt vector can contain 16 exceptions and up to 256 interrupts
+ * In this code we use 16 exceptions and 36 interrupts
+ * (note: this should be aligned to the vector table size)
+ * Offsets of each entry is: 0x0, 0x80, 0x100, 0x180 .. */
+
+/* interrupt vector 1-15: processor exceptions
+ * interrupt vector 16-43: irq0 - irq .. */
+uint32_t ivt[43];
+
+/* * base is location of interrupt service request
+ * */
+void ivt_set_gate(unsigned char num, void * isr(), short pri) {
+
+ ivt[num] = (uint32_t) isr;
+ // TODO priority
+}
+
+// test Interrupt service routine
+void * test_ISR() {
+ uart_puts("PING!");
+}
+
+/* Initialize interrupt vector */
+
+void ivt_init() {
+
+ /* clear entiry IVT, in SRAM location for SRAM + .data (in .bss section) */
+ memset(&ivt, 0, (sizeof(uint32_t) * 44));
+
+ // stack top is loaded from the first entry table on boot/reset
+ // don't need to relocate or init this here
+
+ // copy old vectors
+ extern void * reset, * nmi, * hardfault;
+ //extern uint32_t reset, nmi, hardfault;
+ //ivt[1] = &reset;
+ //ivt[2] = &nmi;
+ //ivt[3] = &hardfault;
+
+ ivt_set_gate(1, test_ISR, 0);
+ ivt_set_gate(2, test_ISR, 0);
+ ivt_set_gate(3, test_ISR, 0);
+ ivt_set_gate(15, test_ISR ,0);
+
+ // enable all interrupts
+
+ *SYSCTRL_RCGC1 = *SYSCTRL_RCGC1 | 0x00010000;
+
+ // TODO systimer
+ // ivt[15]
+ *NVIC_EN0 = *NVIC_EN0 | 0x00008003;
+// *NVIC_EN1 = (volatile uint32_t) 0xFFFFFFFF; // TODO not all registers
+
+ // priority levels are 0 by default (only executable by kernel)
+
+ /* disable all interrupts
+ * MOV R0, #1 ; disable all
+ * MSR PRIMASK, R0
+ * MOV R0, #0 ; allow all
+ * MSR PRIMASK, R0 */
+
+
+
+ /* relocate the vector table to (S)RAM
+ * vector table starts at 0x0. since the address 0x0 point to bootcode, it is on ROM or FLASH.
+ * the value cannot be changed during runtime. however, the vector table can be
+ * relocated to other memory locations in the code or RAM later on
+ *
+ * we can do this by setting a register in the NVIC called
+ * the vector table offset register (address 0xE000ED08). */
+
+
+ *NVIC_VECTTBL = (volatile unsigned long) &ivt;
+
+}
-MEMORY
+/*
+ * MEMORY MAP
{
FLASH (xr) : ORIGIN = 0x00000000, LENGTH = 512K
SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
-}
+} */
ENTRY(_start)
SECTIONS
{
+ . = 0x0;
.text : ALIGN(4)
{
/* (.vector_table */
*(.text)
- } > FLASH
- .data :
+ }
+ . = 0x20000000;
+ .data :
{
*(.data)
- } > SRAM
+ }
+ .bss : ALIGN(256)
+ {
+ *(.bss)
+ }
}
{
uart_init();
uart_puts("LOADING SYSTEM...\n");
+
+ ivt_init();
+
+ //extern void stub();
+ //stub();
+
// loop
for(;;) {
.equ STACK_TOP, 0x20000800
.text
.global _start
+ .global reset, nmi, hardfault
.code 16
.syntax unified
_start:
- .word STACK_TOP, start
- .type start, function
+ .word STACK_TOP, reset, nmi, hardfault
+ .type reset, function
-/* Start of main program */
-start:
+/* A reset vector (or bootcode) will call main in main.c
+ this is the so called 'entry to C' */
+reset:
b main
- b start
+ b reset
+
+/* These are consequently the nmi and hardfault vector handlers
+ before booting and entering main, these can actually be called
+ (machine somehow has a failure). That's why they are included here.
+ Later the interrupt vector
+ will be relocated to SRAM and the will be copied / modified. */
+
+nmi:
+ b nmi
+
+hardfault:
+ b hardfault
+.global stub
+stub:
+ mov r1, #'z'
+ ldr r0, [r1]
+ bx lr
+ /* ldr R0,=10
+ mov R1,#0
+ udiv.w R2, R0, R1 */
.data
-Result:
- .word 'X' /* results now is in 0x20000008 (0x20000000 + 2 w) */
+ .word 'x'
.end
#include <stddef.h>
#include <stdint.h>
#include <stm32.h>
-
-#define SYSCTRL_RCC ((volatile unsigned long *)(0x400FE060))
-#define SYSCTRL_RIS ((volatile unsigned long *)(0x400FE050))
-#define SYSCTRL_RCGC1 ((volatile unsigned long *)(0x400FE104))
-#define SYSCTRL_RCGC2 ((volatile unsigned long *)(0x400FE108))
-#define GPIOPA_AFSEL ((volatile unsigned long *)(0x40004420))
-
-#define UART0_DATA ((volatile unsigned long *)(0x4000C000))
-#define UART0_FLAG ((volatile unsigned long *)(0x4000C018))
-#define UART0_IBRD ((volatile unsigned long *)(0x4000C024))
-#define UART0_FBRD ((volatile unsigned long *)(0x4000C028))
-#define UART0_LCRH ((volatile unsigned long *)(0x4000C02C))
-#define UART0_CTRL ((volatile unsigned long *)(0x4000C030))
-#define UART0_RIS ((volatile unsigned long *)(0x4000C03C))
-
-#define UART1_DATA ((volatile unsigned long *)(0x4000D000))
-#define UART1_FLAG ((volatile unsigned long *)(0x4000D018))
-#define UART1_IBRD ((volatile unsigned long *)(0x4000D024))
-#define UART1_FBRD ((volatile unsigned long *)(0x4000D028))
-#define UART1_LCRH ((volatile unsigned long *)(0x4000D02C))
-#define UART1_CTRL ((volatile unsigned long *)(0x4000D030))
-#define UART1_RIS ((volatile unsigned long *)(0x4000D03C))
-
+#include <mmap.h>
void uart_init() {