diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-01-19 00:03:18 -0700 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-01-19 00:03:18 -0700 |
commit | e5d891fbb9c672cf8c5ec31d7540a9e55747b3a0 (patch) | |
tree | cf95d840084dbcc10fc0e1fe0d0b0c80e1e23b95 /src | |
parent | e4a979594d3df9e158051636a373501942caf044 (diff) | |
download | ch573-e5d891fbb9c672cf8c5ec31d7540a9e55747b3a0.tar.gz ch573-e5d891fbb9c672cf8c5ec31d7540a9e55747b3a0.tar.bz2 ch573-e5d891fbb9c672cf8c5ec31d7540a9e55747b3a0.zip |
Switch to use CMake
Diffstat (limited to 'src')
-rw-r--r-- | src/blinky.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/blinky.c b/src/blinky.c new file mode 100644 index 0000000..ca93df6 --- /dev/null +++ b/src/blinky.c @@ -0,0 +1,90 @@ +#include <stdint.h> + +/* + * 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); + +/* Gpio configuration structure. This is exactly how it is laid out in + * memory. In these registers bit X referes to pin X. */ +typedef struct { + /* The direction of the gpio pin. 1 = output, 0 = input. */ + uint32_t dir; + + /* The value of the gpio pin (for input). */ + uint32_t in; + + /* Write to set the output value for the pin. */ + uint32_t out; + + /* The clear value. Resets the pin to what it is at reset. */ + uint32_t clr; + + /* Sets the pin to be pull-up on logical 1 in input mode. */ + uint32_t pu; + + /* Sets whether the pin should be pull-down (open-drain) for logical 0 or + * drive for logical 1. 1 = pull-down, 0 = drive. */ + uint32_t pd_drv; +} gpio_t; + +/** 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}; + +// GPIO configuration registers. These are defined in the linker script. +extern volatile gpio_t gpio_a; +extern volatile gpio_t gpio_b; + +/* Main routine. This is called on_reset once everything else has been set up. + */ +static void start(void) +{ + uint32_t bit = 1 << 8; + gpio_a.dir |= bit; // Set to "out" + gpio_a.pd_drv |= bit; // Set to "open drain" + + for (;;) { + gpio_a.out &= ~bit; // Pin low (turns on LED) + delay(); + gpio_a.out |= bit; // Pin high (turns off LED) + delay(); + } +} + +/* + * 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 delay(void) +{ + for (volatile uint32_t i = 0; i < 10000; ++i) + ; +} |