#include #include #include "clock.h" #include "io.h" #include "isr_vector.h" void on_reset(void); void __attribute__((weak, interrupt, __section__(".isr_vector.routines"))) default_irq_handler(void) { return; } #define WEAK_IRQ(irq) \ void __attribute__(( \ weak, \ alias("default_irq_handler"), \ __section__(".isr_vector.routines"))) \ irq(void) WEAK_IRQ(irq_on_reset); WEAK_IRQ(irq_on_nmi); WEAK_IRQ(irq_on_exc); WEAK_IRQ(irq_on_systick); WEAK_IRQ(irq_on_swi); WEAK_IRQ(irq_on_tmr0); WEAK_IRQ(irq_on_gpio_a); WEAK_IRQ(irq_on_gpio_b); WEAK_IRQ(irq_on_spi0); WEAK_IRQ(irq_on_blel); WEAK_IRQ(irq_on_bleb); WEAK_IRQ(irq_on_usb); WEAK_IRQ(irq_on_tmr1); WEAK_IRQ(irq_on_tmr2); WEAK_IRQ(irq_on_uart0); WEAK_IRQ(irq_on_uart1); WEAK_IRQ(irq_on_rtc); WEAK_IRQ(irq_on_adc); WEAK_IRQ(irq_on_pwmx); WEAK_IRQ(irq_on_tmr3); WEAK_IRQ(irq_on_uart2); WEAK_IRQ(irq_on_uart3); WEAK_IRQ(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; // Where the data is located in sram. 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; static inline void set_mtvec(void* vector_table) { uint32_t mtvec = (uint32_t)vector_table; mtvec |= 1; // Set interrupt table mode to "VECTORED" asm volatile("csrw mtvec, %0" : : "r"(mtvec)); } /* * Initialize the data segment and the bss segment. * * This function loads data in the .data section from flash and puts it in * memory where it can be edited and initialized the BSS data to 0. */ void init_data_segments(void) { /* 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++); } /* 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++) = 0; } } /* * External reference to the main() function. */ extern int main(void); /* Start function. Responsible for initializing the system and jumping to the * main function. */ static __attribute((__section__(".sinit.1"))) void start(void) { /* Initialize the data segments. */ init_data_segments(); /* Set the mtvec to the isr_vector. */ set_mtvec(&isr_vector); /* Initialize stdout. */ init_uart1_for_stdout(); /* 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__(".sinit"))) void _begin(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)); }