$(CC) $(CFLAGS) -c -I./include -ffreestanding -o main.o main.c
$(CC) $(CFLAGS) -c -I./include -ffreestanding -o uart.o uart.c
$(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
+ $(CC) $(CFLAGS) -c -I./include -ffreestanding -o systick.o systick.c
+ $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o ivt.o systick.o
$(MKIMG) -Obinary -R .data start.out kernel.bin
run:
- qemu-system-arm -serial stdio -M lm3s6965evb -kernel kernel.bin
+ /usr/local/bin/qemu-system-arm -serial stdio -M stm32-f103c8 -kernel kernel.bin
examine:
arm-none-eabi-objdump -S start.out
* 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))
+/* RANDOM DEBUG LOCATION */
+#define RANDOM_ADDR ((volatile uint32_t *)(0x21000000))
-/* SYSTEM CONTROL REGISTERS */
+/* SYSTEM CONTROL BLOCK REGISTER */
+#define SCB_VTOR ((volatile uint32_t *)( 0xE000ED08)) // VECTOR TABLE
+
+/* NESTED VECTOR INTERRUPT CONTROL REGISTER */
+#define NVIC_ISER0 ((volatile uint32_t*)( 0xE000E100)) // interrupt set enable register
+
+/* SYSTICK REGISTER */
+#define STK_CTRL ((volatile uint32_t *)(0xE000E010))
+#define STK_RELOAD ((volatile uint32_t *)(0xE000E014))
+
+
+/* SYSTEM CONTROL REGISTER */
#define SYSCTRL_RCC ((volatile unsigned long *)(0x400FE060))
#define SYSCTRL_RIS ((volatile unsigned long *)(0x400FE050))
#define SYSCTRL_RCGC1 ((volatile unsigned long *)(0x400FE104))
extern void *memset(void*, unsigned char, size_t);
extern unsigned short *memsetw(unsigned short *dest, unsigned short val, size_t count);
extern int strlen(const char *);
-extern unsigned char inportb (uint32_t _addr);
-extern void outportb (uint32_t _addr, unsigned char _data);
/* UART.C */
extern void uart_init();
/* IVT.C */
extern void ivt_init();
+extern void ivt_set_gate(unsigned char, void *(), short);
+
+/* SYSTICK.C */
+extern void systick_init();
#endif
#include <stm32.h>
#include <mmap.h>
-/* TIMER, TODO: move to timer.c */
-
-
+/*
+ * Vector table, each entry contains an interrupt
+ * service routine: *
+ *
+ * interrupt vector 1-15: processor exceptions
+ * interrupt vector 16-32: irq0 - irq ..
+ * */
-/* 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 .. */
+uint32_t ivt[32];
-/* 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
+ *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F));
+ /* Priorities */
}
-// test Interrupt service routine
-void * test_ISR() {
- uart_puts("PING!");
+
+/* Dummy interrupt */
+void * dummy_isr() {
+
}
/* 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));
+ memset(&ivt, 0, (sizeof(uint32_t) * 87));
// 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). */
+ ivt_set_gate(1, dummy_isr, 0);
+ ivt_set_gate(2, dummy_isr, 0);
+ ivt_set_gate(3, dummy_isr, 0);
+ /* the vector table starts at 0x0. Since the address 0x0 point to
+ * bootcode, it is on ROM or FLASH. The vector table can be
+ * relocated to other memory locations. We can do this by setting
+ * a register in the NVIC called the vector table offset register */
- *NVIC_VECTTBL = (volatile unsigned long) &ivt;
+ *SCB_VTOR = (volatile uint32_t) &ivt;
}
/*
* MEMORY MAP
{
- FLASH (xr) : ORIGIN = 0x00000000, LENGTH = 512K
+ FLASH (xr) : ORIGIN = 0x08000000, LENGTH = 512K
SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
} */
return retval;
}
-unsigned char inportb (uint32_t _addr)
-{
- unsigned char rv;
- //__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
- return rv;
-
-}
-void outportb (uint32_t _addr, unsigned char _data)
-{
- // __asm__ __volatile__ ("str %1, %0" : "=r" (_data) : "m" (_addr) );
-
- // __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
-}
void main()
{
- uart_init();
- uart_puts("LOADING SYSTEM...\n");
+ //uart_init();
+ //uart_puts("LOADING SYSTEM...\n");
ivt_init();
-
- //extern void stub();
- //stub();
+ systick_init();
+// asm("cpsie i"); // enable irq , cpsied f (disable faukts(
// loop
for(;;) {
--- /dev/null
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stm32.h>
+#include <mmap.h>
+
+
+void * systick_handler() {
+
+ *RANDOM_ADDR = (volatile uint32_t) 0x10101010 ;
+}
+
+void systick_init() {
+
+ /* Enable the counter and enable the interrupt
+ * associated with it */
+ *STK_CTRL = (volatile uint32_t) 0x00000003;
+
+ /* The counter reload register here holds
+ * 0x1000 -- that's 4096 clock cycles -- if
+ * it is down to zero it is restores the value */
+ *STK_RELOAD = (volatile uint32_t) 0x00000400;
+
+ /* Every time the counter counts down to zero
+ * a systick exception is asserted. Systick has
+ * exception number 15. in the vector table */
+ ivt_set_gate(15, systick_handler, 0);
+}