From d1ebd3bd806f4b4e1f74703f682ca64994c79a28 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Thu, 14 Nov 2024 02:19:09 -0700 Subject: Get a good, basic framework for ISRs and properly handle the data sections. --- src/init.c | 129 +++++++++++++++++++++++++++---------------------------------- 1 file changed, 56 insertions(+), 73 deletions(-) (limited to 'src/init.c') diff --git a/src/init.c b/src/init.c index 8d895f5..a81ce1d 100644 --- a/src/init.c +++ b/src/init.c @@ -2,34 +2,19 @@ #include #include "isr_vector.h" -#include "ch573/gpio.h" - -_Static_assert(offsetof(typeof(isr_vector_t), nmi_cb) == 0x8, "Offset wrong"); - -_Static_assert( - offsetof(typeof(isr_vector_t), systick_cb) == 0x30, "Offset wrong "); - -_Static_assert( - offsetof(typeof(isr_vector_t), tmr0_cb) == 0x40, "Offset wrong "); - -_Static_assert( - offsetof(typeof(isr_vector_t), tmr1_cb) == 0x60, "Offset wrong "); - -_Static_assert( - offsetof(typeof(isr_vector_t), pwmx_cb) == 0x7c, "Offset wrong "); - -_Static_assert( - offsetof(typeof(isr_vector_t), wdog_bat_cb) == 0x8c, "Offset wrong "); void on_reset(void); -void __attribute__((weak, interrupt)) default_irq_handler(void) +void __attribute__((weak, interrupt, __section__(".isr_vector"))) +default_irq_handler(void) { return; } -#define WEAK_IRQ(irq) \ - void __attribute__((weak, alias("default_irq_handler"))) irq(void) +#define WEAK_IRQ(irq) \ + void __attribute__(( \ + weak, alias("default_irq_handler"), __section__(".isr_vector"))) \ + irq(void) WEAK_IRQ(irq_on_nmi); WEAK_IRQ(irq_on_exc); @@ -54,43 +39,28 @@ WEAK_IRQ(irq_on_uart2); WEAK_IRQ(irq_on_uart3); WEAK_IRQ(irq_on_wdog_bat); -/** The ISR Vector structure. This is linked to starting at address 0. */ -__attribute((__section__(".isr_vector"))) volatile isr_vector_t isr_vectors = { - .reset_cb = on_reset, - .nmi_cb = irq_on_nmi, - .exc_cb = irq_on_exc, - .systick_cb = irq_on_systick, - .swi_cb = irq_on_swi, - .tmr0_cb = irq_on_tmr0, - .gpio_a_cb = irq_on_gpio_a, - .gpio_b_cb = irq_on_gpio_b, - .spi0_cb = irq_on_spi0, - .blel_cb = irq_on_blel, - .bleb_cb = irq_on_bleb, - .usb_cb = irq_on_usb, - .tmr1_cb = irq_on_tmr1, - .tmr2_cb = irq_on_tmr2, - .uart0_cb = irq_on_uart0, - .uart1_cb = irq_on_uart1, - .rtc_cb = irq_on_rtc, - .adc_cb = irq_on_adc, - .pwmx_cb = irq_on_pwmx, - .tmr3_cb = irq_on_tmr3, - .uart2_cb = irq_on_uart2, - .uart3_cb = irq_on_uart3, - .wdog_bat_cb = irq_on_wdog_bat, -}; +// Memory-mapped address of the data values in flash. +extern uint32_t ISR_VECTOR_IN_FLASH; + +// Where the data is located in sram. +extern uint32_t ISR_VECTOR_START; +extern uint32_t ISR_VECTOR_STOP; // Memory-mapped address of the data values in flash. -extern uint32_t* DATA_VALUES_IN_FLASH; +extern uint32_t DATA_VALUES_IN_FLASH; // Where the data is located in sram. -extern uint32_t* DATA_SEGMENT_START; -extern uint32_t* DATA_SEGMENT_STOP; +extern uint32_t DATA_SEGMENT_START; +extern uint32_t DATA_SEGMENT_STOP; // Where 0-initialized data is in sram. -extern uint32_t* BSS_START; -extern uint32_t* BSS_STOP; +extern uint32_t BSS_START; +extern uint32_t BSS_STOP; + +static inline void set_mtvec(void* vector_table) +{ + asm volatile("csrw mtvec, %0" : : "r"(vector_table)); +} /* * Initialize the data segment and the bss segment. @@ -100,15 +70,23 @@ extern uint32_t* BSS_STOP; */ void init_data_segments(void) { - uint32_t* src = DATA_VALUES_IN_FLASH; - uint32_t* dest = DATA_SEGMENT_START; + /* Copy the data from the flash to memory. */ + uint32_t* src = &DATA_VALUES_IN_FLASH; + uint32_t* dest = &DATA_SEGMENT_START; + while (dest != &DATA_SEGMENT_STOP) { + *(dest++) = *(src++); + } - while (dest != DATA_SEGMENT_STOP) { + /* Copy the ISR vector to memory. This makes it possible to still recieve + * interrupts even when the flash is powered down. */ + src = &ISR_VECTOR_IN_FLASH; + dest = &ISR_VECTOR_START; + while (dest != &ISR_VECTOR_STOP) { *(dest++) = *(src++); } - dest = BSS_START; - while (dest != BSS_STOP) { + dest = &BSS_START; + while (dest != &BSS_STOP) { *(dest++) = 0; } } @@ -118,26 +96,31 @@ void init_data_segments(void) */ extern void main(void); -#define GPIO_PORT_A ch573_gpio__gpio_port_a -#define GPIO_PORT CH573_GPIO__GPIO_PORT_T_INTF /* Start function. Responsible for initializing the system and jumping to the * main function. */ -// static void start(void) -// { -// // init_data_segments(); -// GPIO_PORT.dir.set(GPIO_PORT_A, DIR_OUT, 8); -// GPIO_PORT.pd_drv.set(GPIO_PORT_A, PD_DRV_OPEN_DRAIN, 8); -// GPIO_PORT.out.set(GPIO_PORT_A, OFF, 8); -// -// main(); -// } - -/* - * The reset callback.This has to be a naked function because the stack pointer - * may not be initialized!!. - */ +static void start(void) +{ + /* Initialize the data segments. */ + init_data_segments(); + /* Set the mtvec to the isr_vector. */ + set_mtvec(&isr_vector); + /* Jump to main */ + main(); +} /* * The reset callback.This has to be a naked function because the stack pointer * may not be initialized!!. */ +__attribute((naked, __section__(".isr_routines.on_reset"))) void on_reset(void) +{ + // Set up the stack pointer to point to the end of SRAM. + asm volatile( + "li sp,0x20008000\n" + "addi sp,sp,-4\n" + "jalr %0\n" + "spin:\n" + "j spin\n" + : + : "r"(start)); +} -- cgit