From ede9bee7f22fd5d0e1bacb7689f1cac23992b70b Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Fri, 15 Nov 2024 02:48:27 -0700 Subject: UART is working. --- fdl/ch573/gpio.fdl | 10 ++++- fdl/ch573/pwr.fdl | 28 +++++++++++++ fdl/ch573/uart.fdl | 11 ++++- include/isr_vector.h | 2 +- linker/ls.ld | 2 + src/blinky.c | 85 ------------------------------------- src/init.c | 12 +++--- src/isr.s | 5 --- src/main.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 172 insertions(+), 99 deletions(-) create mode 100644 fdl/ch573/pwr.fdl delete mode 100644 src/blinky.c create mode 100644 src/main.c diff --git a/fdl/ch573/gpio.fdl b/fdl/ch573/gpio.fdl index c54d956..bab481a 100644 --- a/fdl/ch573/gpio.fdl +++ b/fdl/ch573/gpio.fdl @@ -34,7 +34,10 @@ package ch573.gpio { }; /** Pin input register. */ - reg pin(32); + reg pin(32) : struct { + in : bit_t[16]; + reserved(16); + }; /** Pin output register. */ reg (32) : struct { @@ -46,7 +49,10 @@ package ch573.gpio { reg clr(32); /** Pull-up resistor configuration. */ - reg pu(32); + reg (32) : struct { + pu : enable_t[16]; + reserved(16); + }; /** pull-down/drive configuration register. */ reg (32) : struct { diff --git a/fdl/ch573/pwr.fdl b/fdl/ch573/pwr.fdl new file mode 100644 index 0000000..65f2dbb --- /dev/null +++ b/fdl/ch573/pwr.fdl @@ -0,0 +1,28 @@ +import "ch573/common.fdl"; + +/** Package for the system power control registers. */ +package ch573.pwr { + location pwr_base = 0x4000100C; + + bits clock_source_status_t : enum(1) { + [[ c: unqualified ]] + CLK_SOURCE_ENABLED = 0, + [[ c: unqualified ]] + CLK_SOURCE_DISABLED = 1, + }; + + type pwr_mgmt_t : struct { + reg slp_clk_off_0(8) : struct { + tmr0 : clock_source_status_t; + tmr1 : clock_source_status_t; + tmr2 : clock_source_status_t; + tmr3 : clock_source_status_t; + uart0 : clock_source_status_t; + uart1 : clock_source_status_t; + uart2 : clock_source_status_t; + uart3 : clock_source_status_t; + }; + }; + + instance pwr_mgmt at pwr_base : pwr_mgmt_t; +}; diff --git a/fdl/ch573/uart.fdl b/fdl/ch573/uart.fdl index bc2df2d..9a4f0c5 100644 --- a/fdl/ch573/uart.fdl +++ b/fdl/ch573/uart.fdl @@ -70,7 +70,16 @@ package ch573.uart { /** Line Control Register */ reg lcr(8) : struct { /** UART word size (5-8 bits) */ - word_sz : (2); + word_sz : enum(2) { + [[ c: unqualified ]] + WORD_SZ_5_BITS = 0b00, + [[ c: unqualified ]] + WORD_SZ_6_BITS = 0b01, + [[ c: unqualified ]] + WORD_SZ_7_BITS = 0b10, + [[ c: unqualified ]] + WORD_SZ_8_BITS = 0b11, + }; /** Stop bit setting */ stop_bit : bit_t; /** Parity bit enable */ diff --git a/include/isr_vector.h b/include/isr_vector.h index 65359a5..6059875 100644 --- a/include/isr_vector.h +++ b/include/isr_vector.h @@ -46,7 +46,7 @@ void irq_on_wdog_bat(void); * long jump). This stub is compiled and linked promimal to the ISR vector. \ */ \ void __attribute__((interrupt)) \ - __attribute__((__section__(".isr_vector"))) irq_on_##name(void) \ + __attribute__((__section__(".isr_vector.routines"))) irq_on_##name(void) \ { \ _real__irq_on_##name(); \ } \ diff --git a/linker/ls.ld b/linker/ls.ld index 18ee181..916438b 100644 --- a/linker/ls.ld +++ b/linker/ls.ld @@ -10,6 +10,7 @@ SECTIONS .text : ALIGN(0x04) { *(.sinit); + *(.sinit.1); /* The ch573 starts execution at address 0x0000, so we have to make sure the * on_reset function is put at the beginning of the flash. */ @@ -23,6 +24,7 @@ SECTIONS .isr_vector : ALIGN(0x04) { ISR_VECTOR_START = .; *(.isr_vector); + *(.isr_vector.routines); ISR_VECTOR_STOP = .; } >sram AT>flash diff --git a/src/blinky.c b/src/blinky.c deleted file mode 100644 index 355b479..0000000 --- a/src/blinky.c +++ /dev/null @@ -1,85 +0,0 @@ -#include - -#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 - -/* - * Function which delays for a bit. - */ -void delay(void); - -void main(void); - -uint32_t collatz(uint32_t n) -{ - uint32_t c = 0; - - while (n > 1) { - if (n % 2 == 0) { - n /= 2; - } else { - n = n * 3 + 1; - } - c++; - } - - return c; -} - -void blink_n(int n) -{ - uint32_t bit = 1 << 8; - while (n > 0) { - GPIO_PORT.out.set(GPIO_PORT_A, OFF, 8); - delay(); - GPIO_PORT.out.set(GPIO_PORT_A, ON, 8); - delay(); - --n; - } -} - -void delay(void) -{ - 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. - */ -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 (;;) { - 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(); - } -} - -IRQ(systick) { - collatz(5); -} - -IRQ(exc) {} - -IRQ(nmi) {} diff --git a/src/init.c b/src/init.c index 30e2c6d..5753a13 100644 --- a/src/init.c +++ b/src/init.c @@ -5,7 +5,7 @@ void on_reset(void); -void __attribute__((weak, interrupt, __section__(".isr_vector"))) +void __attribute__((weak, interrupt, __section__(".isr_vector.routines"))) default_irq_handler(void) { return; @@ -13,7 +13,7 @@ default_irq_handler(void) #define WEAK_IRQ(irq) \ void __attribute__(( \ - weak, alias("default_irq_handler"), __section__(".isr_vector"))) \ + weak, alias("default_irq_handler"), __section__(".isr_vector.routines"))) \ irq(void) WEAK_IRQ(irq_on_reset); @@ -60,7 +60,9 @@ extern uint32_t BSS_STOP; static inline void set_mtvec(void* vector_table) { - asm volatile("csrw mtvec, %0" : : "r"(vector_table)); + uint32_t mtvec = (uint32_t) vector_table; + mtvec |= 1; // Set interrupt table mode to "VECTORED" + asm volatile("csrw mtvec, %0" : : "r"(mtvec)); } /* @@ -99,7 +101,7 @@ extern void main(void); /* Start function. Responsible for initializing the system and jumping to the * main function. */ -static void start(void) +static __attribute((__section__(".sinit.1"))) void start(void) { /* Initialize the data segments. */ init_data_segments(); @@ -113,7 +115,7 @@ static void start(void) * 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) +__attribute((naked, __section__(".sinit"))) void _begin(void) { // Set up the stack pointer to point to the end of SRAM. asm volatile( diff --git a/src/isr.s b/src/isr.s index 065450d..04d66d1 100644 --- a/src/isr.s +++ b/src/isr.s @@ -1,8 +1,3 @@ - -.section .sinit -_start: -j on_reset /* first instruction. Should jump directly to on_reset */ - .section .isr_vector .global isr_vector isr_vector: diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..3066123 --- /dev/null +++ b/src/main.c @@ -0,0 +1,116 @@ +#include + +#include "ch573/gpio.h" +#include "ch573/uart.h" +#include "ch573/pwr.h" + +#include "isr_vector.h" + +#define GPIO_PORT_A ch573_gpio__gpio_port_a +#define GPIO_PORT CH573_GPIO__GPIO_PORT_T_INTF + +#define UART1 ch573_uart__uart1 +#define UART CH573_UART__UART_T_INTF + +#define PWR1 ch573_pwr__pwr_mgmt +#define PWR CH573_PWR__PWR_MGMT_T_INTF + +/* + * Function which delays for a bit. + */ +void delay(void); + +void main(void); + +uint32_t collatz(uint32_t n) +{ + uint32_t c = 0; + + while (n > 1) { + if (n % 2 == 0) { + n /= 2; + } else { + n = n * 3 + 1; + } + c++; + } + + return c; +} + +void blink_n(int n) +{ + uint32_t bit = 1 << 8; + while (n > 0) { + GPIO_PORT.out.set(GPIO_PORT_A, OFF, 8); + delay(); + GPIO_PORT.out.set(GPIO_PORT_A, ON, 8); + delay(); + --n; + } +} + +void delay(void) +{ + 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; + +#define gpio_usart1_tx_pin 9 +#define gpio_usart1_rx_pin 8 + +const char* hello_world = "Hello, World!\r\n"; + +#define BAUD_RATE 115200 + +/* Main routine. This is called on_reset once everything else has been set up. + */ +void main(void) +{ + GPIO_PORT.dir.set(GPIO_PORT_A, DIR_OUT, gpio_usart1_tx_pin); + GPIO_PORT.pd_drv.set(GPIO_PORT_A, 0, gpio_usart1_tx_pin); + + UART.div.set(UART1, 1); + UART.fcr.set(UART1, 0x07); + UART.ier.txd_en.set(UART1, ON); + UART.lcr.word_sz.set(UART1, WORD_SZ_8_BITS); + + uint32_t dl = (10 * 6400000 / 8 / BAUD_RATE + 5) / 10; + UART.dl.set(UART1, dl); + + // PWR.slp_clk_off_0.uart1.set(PWR1, CLK_SOURCE_ENABLED); + + const char* ptr = hello_world; + + while (1) { + if (*ptr == 0) { + ptr = hello_world; + } + + while (!UART.lsr.thr_empty.get(UART1)); + UART.thr.set(UART1, *(ptr++)); + } +} + +IRQ(systick) +{ + collatz(5); +} + +IRQ(exc) +{ +} + +IRQ(nmi) +{ +} -- cgit