From ef5f6398b258318ad024824341ad802593ad4c2c Mon Sep 17 00:00:00 2001 From: Ilia Sergachev Date: Sun, 23 Jan 2022 11:02:36 +0100 Subject: [PATCH 1/6] integration/builder: enable bios on gowin emcu --- litex/soc/integration/builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/integration/builder.py b/litex/soc/integration/builder.py index 50e08dbed..acbdc47a5 100644 --- a/litex/soc/integration/builder.py +++ b/litex/soc/integration/builder.py @@ -281,7 +281,7 @@ class Builder: self.soc.platform.output_dir = self.output_dir # Check if BIOS is used and add software package if so. - with_bios = self.soc.cpu_type not in [None, 'gowin_emcu'] + with_bios = self.soc.cpu_type is not None if with_bios: self.add_software_package("bios") From 3f2a7b9bfd030ebaa5a0c27c2896ccbfd6c095de Mon Sep 17 00:00:00 2001 From: Ilia Sergachev Date: Sun, 23 Jan 2022 11:04:22 +0100 Subject: [PATCH 2/6] software/bios: set attribute used on main to fix optimization in some configurations --- litex/soc/software/bios/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index 56042538b..13ae2d6c2 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -74,7 +74,7 @@ static void boot_sequence(void) printf("No boot medium found\n"); } -int main(int i, char **c) +__attribute__((__used__)) int main(int i, char **c) { char buffer[CMD_LINE_BUFFER_SIZE]; char *params[MAX_PARAM]; From d4c12a523144710c5f534ee24421e4d61ae38121 Mon Sep 17 00:00:00 2001 From: Ilia Sergachev Date: Sun, 23 Jan 2022 11:20:16 +0100 Subject: [PATCH 3/6] cores/cpu/gowin_emcu: add software support --- litex/soc/cores/cpu/gowin_emcu/boot-helper.c | 5 ++ litex/soc/cores/cpu/gowin_emcu/core.py | 3 +- litex/soc/cores/cpu/gowin_emcu/crt0.c | 44 ++++++++++++ litex/soc/cores/cpu/gowin_emcu/irq.h | 37 ++++++++++ litex/soc/cores/cpu/gowin_emcu/system.h | 72 ++++++++++++++++++++ 5 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 litex/soc/cores/cpu/gowin_emcu/boot-helper.c create mode 100644 litex/soc/cores/cpu/gowin_emcu/crt0.c create mode 100644 litex/soc/cores/cpu/gowin_emcu/irq.h create mode 100644 litex/soc/cores/cpu/gowin_emcu/system.h diff --git a/litex/soc/cores/cpu/gowin_emcu/boot-helper.c b/litex/soc/cores/cpu/gowin_emcu/boot-helper.c new file mode 100644 index 000000000..4dd8ae2d3 --- /dev/null +++ b/litex/soc/cores/cpu/gowin_emcu/boot-helper.c @@ -0,0 +1,5 @@ +void boot_helper(unsigned long r1, unsigned long r2, unsigned long r3, unsigned long addr); + +void boot_helper(unsigned long r1, unsigned long r2, unsigned long r3, unsigned long addr) { + goto *addr; +} diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index 407cbd27d..81afa60a4 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -61,7 +61,7 @@ class GowinEMCU(CPU): io_regions = { # Origin, Length. 0x4000_0000: 0x2000_0000, - 0xa000_0000: 0x6000_0000 + 0xA000_0000: 0x6000_0000 } @property @@ -69,6 +69,7 @@ class GowinEMCU(CPU): return { "rom": 0x0000_0000, "sram": 0x2000_0000, + "peripherals": 0x4000_0000, "csr": 0xA000_0000, } diff --git a/litex/soc/cores/cpu/gowin_emcu/crt0.c b/litex/soc/cores/cpu/gowin_emcu/crt0.c new file mode 100644 index 000000000..95c7a6f1c --- /dev/null +++ b/litex/soc/cores/cpu/gowin_emcu/crt0.c @@ -0,0 +1,44 @@ +#include + +extern uint32_t _fdata_rom, _fdata, _edata, _fbss, _ebss, _fstack; + +void _start(void); +void default_handler(void); + +void _start(void) { + uint32_t *y = &_fdata_rom; + for (uint32_t *x = &_fdata; x < &_edata; x ++) + *x = *y ++; + + for (uint32_t *x = &_fbss; x < &_ebss; x ++) + *x = 0; + + // TODO: init uart + + __asm__("bl main"); + while(1); +} + +void default_handler(void) { + while(1); +} + + +const void* isr_vector[] __attribute__ ((section(".isr_vector"))) = { + &_fstack, + _start, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + 0, + 0, + 0, + 0, + default_handler, + default_handler, + 0, + default_handler, + default_handler +}; diff --git a/litex/soc/cores/cpu/gowin_emcu/irq.h b/litex/soc/cores/cpu/gowin_emcu/irq.h new file mode 100644 index 000000000..4c87950ef --- /dev/null +++ b/litex/soc/cores/cpu/gowin_emcu/irq.h @@ -0,0 +1,37 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +static inline unsigned int irq_getie(void) +{ + return 0; /* FIXME */ +} + +static inline void irq_setie(unsigned int ie) +{ + /* FIXME */ +} + +static inline unsigned int irq_getmask(void) +{ + return 0; /* FIXME */ +} + +static inline void irq_setmask(unsigned int mask) +{ + /* FIXME */ +} + +static inline unsigned int irq_pending(void) +{ + return 0; /* FIXME */ +} + +#ifdef __cplusplus +} +#endif + +#endif /* __IRQ_H */ diff --git a/litex/soc/cores/cpu/gowin_emcu/system.h b/litex/soc/cores/cpu/gowin_emcu/system.h new file mode 100644 index 000000000..2fc3a77d1 --- /dev/null +++ b/litex/soc/cores/cpu/gowin_emcu/system.h @@ -0,0 +1,72 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((unused)) static void flush_cpu_icache(void){}; +__attribute__((unused)) static void flush_cpu_dcache(void){}; +void flush_l2_cache(void); + +void busy_wait(unsigned int ms); +void busy_wait_us(unsigned int us); + +#include + +// FIXME +#define CSR_UART_BASE +#define UART_POLLING + +struct EMCU_UART +{ + volatile uint32_t data; + volatile uint32_t state; + volatile uint32_t ctrl; + volatile uint32_t int_ctrl; + volatile uint32_t baud_div; +}; + +#define PERIPHERALS_BASE 0x40000000 +#define UART0 ((struct EMCU_UART *) (PERIPHERALS_BASE + 0x4000)) + +static inline char uart_txfull_read(void); +static inline char uart_rxempty_read(void); +static inline void uart_ev_enable_write(char c); +static inline void uart_rxtx_write(char c); +static inline char uart_rxtx_read(void); +static inline void uart_ev_pending_write(char); +static inline char uart_ev_pending_read(void); + +static inline char uart_txfull_read(void) { + return UART0->state & 0b01; +} + +static inline char uart_rxempty_read(void) { + return !(UART0->state & 0b10); +} + +static inline void uart_ev_enable_write(char c) { + // FIXME +} + +static inline void uart_rxtx_write(char c) { + UART0->data = (uint32_t) c; +} + +static inline char uart_rxtx_read(void) +{ + return (char)(UART0->data); +} + +static inline void uart_ev_pending_write(char x) {} +static inline char uart_ev_pending_read(void) { + return 0; +} + + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_H */ From 0f44723957bbd837b521a81b4e18945142ac9eff Mon Sep 17 00:00:00 2001 From: Ilia Sergachev Date: Sun, 23 Jan 2022 15:37:00 +0100 Subject: [PATCH 4/6] cores/cpu/gowin: fix isr table optimization and uart init --- litex/soc/cores/cpu/gowin_emcu/crt0.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/crt0.c b/litex/soc/cores/cpu/gowin_emcu/crt0.c index 95c7a6f1c..bea687093 100644 --- a/litex/soc/cores/cpu/gowin_emcu/crt0.c +++ b/litex/soc/cores/cpu/gowin_emcu/crt0.c @@ -1,4 +1,6 @@ #include +#include "system.h" +#include "generated/soc.h" extern uint32_t _fdata_rom, _fdata, _edata, _fbss, _ebss, _fstack; @@ -6,17 +8,18 @@ void _start(void); void default_handler(void); void _start(void) { - uint32_t *y = &_fdata_rom; - for (uint32_t *x = &_fdata; x < &_edata; x ++) - *x = *y ++; + uint32_t *y = &_fdata_rom; + for (uint32_t *x = &_fdata; x < &_edata; x ++) + *x = *y ++; - for (uint32_t *x = &_fbss; x < &_ebss; x ++) - *x = 0; + for (uint32_t *x = &_fbss; x < &_ebss; x ++) + *x = 0; - // TODO: init uart + UART0->ctrl = 0b11; // set rx and tx enable bits + UART0->baud_div = CONFIG_CLOCK_FREQUENCY / 115200; // FIXME - __asm__("bl main"); - while(1); + __asm__("bl main"); + while(1); } void default_handler(void) { @@ -24,7 +27,7 @@ void default_handler(void) { } -const void* isr_vector[] __attribute__ ((section(".isr_vector"))) = { +const void* isr_vector[] __attribute__((__used__)) __attribute__((section(".isr_vector"))) = { &_fstack, _start, default_handler, From 85f892227afc622d30ec73b3f399155dca7b8896 Mon Sep 17 00:00:00 2001 From: Ilia Sergachev Date: Sun, 23 Jan 2022 16:34:47 +0100 Subject: [PATCH 5/6] cores/cpu/gowin: re-enable write access to csr bus --- litex/soc/cores/cpu/gowin_emcu/core.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index 81afa60a4..c30b50061 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -169,9 +169,6 @@ class GowinEMCU(CPU): self.periph_buses = [self.pbus] ahb_targexp0 = ahb.Interface() for s, _ in ahb_targexp0.master_signals: - # TODO: due to unexpected writes by the CPU bus is currently forced read-only - if s == "write": - continue self.cpu_params[f"o_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s) for s, _ in ahb_targexp0.slave_signals: self.cpu_params[f"i_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s) From f36619987b6ea2a1c9e5c9faeb961b812769d052 Mon Sep 17 00:00:00 2001 From: Ilia Sergachev Date: Sun, 23 Jan 2022 16:57:33 +0100 Subject: [PATCH 6/6] software/bios: update comment --- litex/soc/software/bios/linker.ld | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litex/soc/software/bios/linker.ld b/litex/soc/software/bios/linker.ld index ea932f88b..66f8b9aff 100644 --- a/litex/soc/software/bios/linker.ld +++ b/litex/soc/software/bios/linker.ld @@ -8,8 +8,8 @@ SECTIONS .text : { _ftext = .; - /* Quicklogic EOS-S3 interrupt vector table uses section name "isr_vector" */ - /* ARM table has to be placed at start */ + /* ARM (Quicklogic EOS-S3, Gowin EMCU) interrupt vector tables use section name "isr_vector" */ + /* - such a table has to be placed at start */ KEEP(*(.isr_vector)) /* Make sure crt0 files come first, and they, and the isr */ /* don't get disposed of by greedy optimisation */