From 968937d0d937487ab301f017c145889fc0e94692 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Wed, 15 Sep 2021 23:16:11 +0200 Subject: platforms: Add initial RISC-V/GD32V support. --- interrupt/SConscript | 16 ++++++++ interrupt/clic.h | 33 +++++++++++++++ interrupt/dispatch_clic.cpp | 25 ++++++++++++ interrupt/dispatch_plic.cpp | 8 ++++ interrupt/dispatch_riscv.cpp | 24 +++++++++++ interrupt/plic.h | 25 ++++++++++++ interrupt/vectors_clic.cpp.j2 | 23 +++++++++++ interrupt/vectors_generic.cpp.j2 | 14 +++++++ platforms/gd32v.yaml | 88 ++++++++++++++++++++++++++++++++++++++++ platforms/index.yaml | 10 +++++ platforms/riscv.yaml | 38 +++++++++++++++++ 11 files changed, 304 insertions(+) create mode 100644 interrupt/clic.h create mode 100644 interrupt/dispatch_clic.cpp create mode 100644 interrupt/dispatch_plic.cpp create mode 100644 interrupt/dispatch_riscv.cpp create mode 100644 interrupt/plic.h create mode 100644 interrupt/vectors_clic.cpp.j2 create mode 100644 interrupt/vectors_generic.cpp.j2 create mode 100644 platforms/gd32v.yaml create mode 100644 platforms/riscv.yaml diff --git a/interrupt/SConscript b/interrupt/SConscript index 2380815..4544785 100644 --- a/interrupt/SConscript +++ b/interrupt/SConscript @@ -30,6 +30,22 @@ if 'nvic' in periph: env.Jinja2('vectors_nvic.cpp', 'vectors_nvic.cpp.j2', interrupts = interrupts), ]) +if 'clic' in periph: + headers.append('clic.h') + for name, data in periph['clic'].items(): + instances.append({ + 'type': 'CLIC_t', + 'name': name, + 'args': [data['offset']], + }) + + aliases['interrupt_ctl'] = 'CLIC' + + sources.extend([ + File('dispatch_clic.cpp'), + env.Jinja2('vectors_clic.cpp', 'vectors_clic.cpp.j2', interrupts = interrupts), + ]) + env.Jinja2('interrupt.h', '../templates/periph_instances.h.j2', headers = headers, instances = instances, aliases = aliases) Return('sources') diff --git a/interrupt/clic.h b/interrupt/clic.h new file mode 100644 index 0000000..247aeec --- /dev/null +++ b/interrupt/clic.h @@ -0,0 +1,33 @@ +#pragma once + +#include "interrupt_enums.h" + +#include + +struct CLIC_int_reg_t { + volatile uint8_t IP; + volatile uint8_t IE; + volatile uint8_t ATTR; + volatile uint8_t CTL; +}; + +struct CLIC_reg_t { + volatile uint32_t CFG; + volatile uint32_t INFO; + uint32_t _reserved[14]; + volatile uint32_t TRIG[32]; + uint32_t _reserved2[976]; + CLIC_int_reg_t INT[4096]; +}; + + +class CLIC_t : public mmio_ptr { + public: + void enable(interrupt::irq n) const { + ptr()->INT[int(n)].IE = 1; + } + + void enable(interrupt::internal n) const { + ptr()->INT[int(n)].IE = 1; + } +}; diff --git a/interrupt/dispatch_clic.cpp b/interrupt/dispatch_clic.cpp new file mode 100644 index 0000000..64e4bfc --- /dev/null +++ b/interrupt/dispatch_clic.cpp @@ -0,0 +1,25 @@ +#include "interrupt.h" + +extern interrupt::vector_t vectors_exception[]; +extern interrupt::vector_t vectors_clic[]; + +[[gnu::interrupt, gnu::aligned(64)]] +void riscv_interrupt_handler() { + uint32_t cause; + asm("csrr %0, mcause" : "=r"(cause)); + + uint32_t type = cause & 0x80000000; + uint32_t code = cause & 0x00000fff; + + if(type) { + vectors_clic[code](); + } else { + vectors_exception[code](); + } +} + +[[gnu::constructor(200)]] +void riscv_interrupt_init() { + asm volatile("csrw mtvec, %0" :: "r"(intptr_t(riscv_interrupt_handler) | 3)); + asm volatile("csrrsi x0, mstatus, (1 << 3)"); +} diff --git a/interrupt/dispatch_plic.cpp b/interrupt/dispatch_plic.cpp new file mode 100644 index 0000000..081013d --- /dev/null +++ b/interrupt/dispatch_plic.cpp @@ -0,0 +1,8 @@ +#include "interrupt.h" + +extern interrupt::vector_t vectors_irq[]; + +template<> +void interrupt::handler() { + while(1) {} +} diff --git a/interrupt/dispatch_riscv.cpp b/interrupt/dispatch_riscv.cpp new file mode 100644 index 0000000..a91e95a --- /dev/null +++ b/interrupt/dispatch_riscv.cpp @@ -0,0 +1,24 @@ +#include "interrupt.h" + +extern interrupt::vector_t vectors_exception[]; +extern interrupt::vector_t vectors_internal[]; + +[[gnu::interrupt]] +void riscv_interrupt_handler() { + uint32_t cause; + asm("csrr %0, mcause" : "=r"(cause)); + + uint32_t type = cause & 0x80000000; + uint32_t code = cause & 0x7fffffff; + + if(type) { + vectors_internal[code](); + } else { + vectors_exception[code](); + } +} + +[[gnu::constructor(200)]] +void riscv_interrupt_init() { + asm volatile("csrw mtvec, %0" :: "r"(riscv_interrupt_handler)); +} diff --git a/interrupt/plic.h b/interrupt/plic.h new file mode 100644 index 0000000..46ade92 --- /dev/null +++ b/interrupt/plic.h @@ -0,0 +1,25 @@ +#pragma once + +class PLIC_t { + private: + struct PLIC_ctx_reg_t { + volatile uint32_t THRESHOLD; + volatile uint32_t CLAIM; + uint32_t _reserved[1022]; + }; + + struct PLIC_reg_t { + volatile uint32_t PRIO[1024]; + volatile uint32_t PEND[32]; + uint32_t _reserved[992]; + volatile uint32_t ENABLE[15872][32]; + uint32_t _reserved2[14336]; + PLIC_ctx_reg_t CTX[15872]; + }; + + public: + PLIC_reg_t& reg; + + PLIC_t(uint32_t reg_addr) : + reg(*(PLIC_reg_t*)reg_addr) {} +}; diff --git a/interrupt/vectors_clic.cpp.j2 b/interrupt/vectors_clic.cpp.j2 new file mode 100644 index 0000000..7f9dd9f --- /dev/null +++ b/interrupt/vectors_clic.cpp.j2 @@ -0,0 +1,23 @@ +#include "interrupt.h" + +interrupt::vector_t vectors_clic[] = { + {% for i in range(interrupts.irq | max + 1 if interrupts.irq else interrupts.internal | max + 1 if interrupts.internal else 0) %} + {% if i in interrupts.internal %} + interrupt::handler, + {% elif i in interrupts.irq %} + interrupt::handler, + {% else %} + 0, + {% endif %} + {% endfor %} +}; + +interrupt::vector_t vectors_exception[] = { + {% for i in range(interrupts.exception | max + 1 if interrupts.exception else 0) %} + {% if i in interrupts.exception %} + interrupt::handler, + {% else %} + 0, + {% endif %} + {% endfor %} +}; diff --git a/interrupt/vectors_generic.cpp.j2 b/interrupt/vectors_generic.cpp.j2 new file mode 100644 index 0000000..26ef05d --- /dev/null +++ b/interrupt/vectors_generic.cpp.j2 @@ -0,0 +1,14 @@ +#include "interrupt.h" + +{% for type, entries in interrupts.items() %} + interrupt::vector_t vectors_{{ type }}[] = { + {% for i in range(entries | max + 1 if entries else 0) %} + {% if i in entries %} + interrupt::handler, + {% else %} + 0, + {% endif %} + {% endfor %} + }; + +{% endfor %} diff --git a/platforms/gd32v.yaml b/platforms/gd32v.yaml new file mode 100644 index 0000000..34b2bf8 --- /dev/null +++ b/platforms/gd32v.yaml @@ -0,0 +1,88 @@ +- match: + mcu: !re gd32vf103 + mem: + flash: + origin: 0x08000000 + size: 128k + + ram: + origin: 0x20000000 + size: 32k + + periph: + clic: + CLIC: + offset: 0xd2000000 + + dwc_otg: + OTG_FS: + offset: 0x50000000 + + rcc: + RCC: + offset: 0x40021000 + type: f1 + bus: + AHB: + 0: DMA1 + 1: DMA2 + 2: SRAM + 4: FLITF + 6: CRC + 8: FSMC + 10: SDIO + 12: USBFS + + APB1: + 0: TIM2 + 1: TIM3 + 2: TIM4 + 3: TIM5 + 4: TIM6 + 5: TIM7 + 6: TIM12 + 7: TIM13 + 8: TIM14 + 11: WWDG + 14: SPI2 + 15: SPI3 + 17: USART2 + 18: USART3 + 19: UART4 + 20: UART5 + 21: I2C1 + 22: I2C2 + 25: CAN + 27: BKP + 28: PWR + 29: DAC + + APB2: + 0: AFIO + 2: GPIOA + 3: GPIOB + 4: GPIOC + 5: GPIOD + 6: GPIOE + 7: GPIOF + 8: GPIOG + 9: ADC1 + 10: ADC2 + 11: TIM1 + 12: SPI1 + 13: TIM8 + 14: USART1 + 15: ADC3 + 19: TIM9 + 20: TIM10 + 21: TIM11 + + interrupt: + irq: + 56: USART1 + + define: + - STM32F1 + + meta: + cpu: rv32imac \ No newline at end of file diff --git a/platforms/index.yaml b/platforms/index.yaml index 558b535..15a83e6 100644 --- a/platforms/index.yaml +++ b/platforms/index.yaml @@ -3,7 +3,17 @@ -: !import stm32/index.yaml +- match: + mcu: !re gd32v + + -: !import gd32v.yaml + - match: cpu: !re cortex-m -: !import cortex-m.yaml + +- match: + cpu: !re rv + + -: !import riscv.yaml \ No newline at end of file diff --git a/platforms/riscv.yaml b/platforms/riscv.yaml new file mode 100644 index 0000000..ec9ecd7 --- /dev/null +++ b/platforms/riscv.yaml @@ -0,0 +1,38 @@ +- match: + cpu: rv32imac + + cflags: + - -march=rv32imac + - -mabi=ilp32 + - -msmall-data-limit=0 + + interrupt: + exception: + 0: InstructionMisaligned + 1: InstructionFault + 2: IllegalInstruction + 3: Breakpoint + 4: LoadMisaligned + 5: LoadFault + 6: StoreMisaligned + 7: StoreFault + 8: ECall_U + 9: ECall_S + 11: ECall_M + 12: InstructionPageFault + 13: LoadPageFault + 15: StorePageFault + + internal: + 0: USI + 1: SSI + 3: MSI + 4: UTI + 5: STI + 7: MTI + 8: UEI + 9: SEI + 11: MEI + + toolchains: + - riscv64-unknown-elf -- cgit v1.2.3