aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/blinky.c74
-rw-r--r--src/init.c129
-rw-r--r--src/isr.s54
3 files changed, 130 insertions, 127 deletions
diff --git a/src/blinky.c b/src/blinky.c
index d8a29bd..9f89238 100644
--- a/src/blinky.c
+++ b/src/blinky.c
@@ -1,50 +1,19 @@
#include <stdint.h>
+#include "isr_vector.h"
#include "ch573/gpio.h"
#define GPIO_PORT_A ch573_gpio__gpio_port_a
#define GPIO_PORT CH573_GPIO__GPIO_PORT_T_INTF
-static void start(void);
-
-/*
- * Function (or really pointer to code) for the reset interrupt handler.
- */
-void on_reset(void);
-
/*
* Function which delays for a bit.
*/
void delay(void);
-/* Type def to a void function to make things mor ereadable. */
-typedef void (*isr_routine)(void);
-
-/** The ISR Vector structure. This is linked to starting at address 0. */
-// __attribute((__section__(".isr_vector"))) volatile struct {
-// // What NULL points to. nothing useful.
-// uint32_t reserved__;
-// // Called when the device boots or reset is pressed.
-// isr_routine reset_cb;
-// isr_routine nmi_cb;
-// isr_routine exc_cb;
-// } isr_vectors = {.reset_cb = on_reset};
-
-/*
- * The reset callback.This has to be a naked function because the stack pointer
- * may not be initialized!!.
- */
-__attribute((naked)) 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));
+void main(void);
+IRQ(irq_on_systick) {
+ main();
}
uint32_t collatz(uint32_t n)
@@ -77,38 +46,35 @@ void blink_n(int n)
void delay(void)
{
- for (volatile uint32_t i = 0; i < 10000; ++i);
+ for (volatile uint32_t i = 0; i < 10000; ++i) {
+ asm volatile("");
+ }
}
+volatile uint32_t deadbeef = 0xdeadbeef;
+
+// 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;
+
/* Main routine. This is called on_reset once everything else has been set up.
*/
-static void start(void)
+void main(void)
{
GPIO_PORT.dir.set(GPIO_PORT_A, DIR_OUT, 8);
GPIO_PORT.pd_drv.set(GPIO_PORT_A, PD_DRV_OPEN_DRAIN, 8);
for (;;) {
- GPIO_PORT.out.set(GPIO_PORT_A, ON, 8);
+ if (deadbeef == 0xdeadbeef) {
+ GPIO_PORT.out.set(GPIO_PORT_A, ON, 8);
+ }
delay();
delay();
delay();
GPIO_PORT.out.set(GPIO_PORT_A, OFF, 8);
delay();
}
-
- // uint32_t i;
- // for (i = 1;; ++i) {
- // uint32_t c = collatz(i);
- // blink_n(c);
-
- // delay();
- // delay();
- // delay();
- // delay();
- // delay();
- // delay();
- // delay();
- // delay();
- // delay();
- // }
}
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 <stdint.h>
#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));
+}
diff --git a/src/isr.s b/src/isr.s
new file mode 100644
index 0000000..6a9e6cf
--- /dev/null
+++ b/src/isr.s
@@ -0,0 +1,54 @@
+
+.section .sinit
+_start:
+j on_reset /* first instruction. Should jump directly to on_reset */
+
+.section .isr_vector
+.global isr_vector
+isr_vector:
+.align 4
+.word 0
+ j irq_on_nmi
+ j irq_on_exc
+
+.word 0
+.word 0
+.word 0
+.word 0
+.word 0
+.word 0
+.word 0
+.word 0
+
+ j irq_on_systick
+
+.word 0
+
+ j irq_on_swi
+
+.word 0
+
+ j irq_on_tmr0
+ j irq_on_gpio_a
+ j irq_on_gpio_b
+ j irq_on_spi0
+ j irq_on_blel
+ j irq_on_bleb
+ j irq_on_usb
+
+.word 0
+
+ j irq_on_tmr1
+ j irq_on_tmr2
+ j irq_on_uart0
+ j irq_on_uart1
+ j irq_on_rtc
+ j irq_on_adc
+
+.word 0
+
+ j irq_on_pwmx
+ j irq_on_tmr3
+ j irq_on_uart2
+ j irq_on_uart3
+ j irq_on_wdog_bat