This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 5f2dadf17d519caf2374501650148fe721a0461e Author: Alan Carvalho de Assis <[email protected]> AuthorDate: Sat Oct 24 21:23:42 2026 -0300 arch/risc-v/ab32vg1: add Bluetrum AB32VG1 chip support Add support for the Bluetrum AB32VG1 (AB5301A, "CRWN"), an RV32IMC Bluetooth audio SoC with 192 KB of RAM and 1 MB of in-package flash. The AB32VG1 core implements the RISC-V unprivileged ISA but not the standard machine-mode trap architecture: there are no CSRs (any CSR access, ecall or ebreak raises an exception it cannot resume from) and interrupts are controlled through memory-mapped registers. Add a hidden ARCH_RV_CUSTOM_TRAP option that lets such a chip provide up_irq_save()/up_irq_restore() and the system call instruction through <arch/chip/trap.h>, and its own trap entry, up_saveusercontext() and initial interrupt context instead of the CSR-based common files. No functional change for other chips. AB32VG1 support: - Trap entry through a RAM vector table (PICADR); EPC/EPICCON are memory-mapped and mret restores the interrupt enable, also from thread mode. System calls use a software trap that builds the same frame as a hardware trap with interrupts masked. Exceptions are reported and fatal. - System clock (PLL0 / n, 48 MHz default), TMR0 system tick, interrupt controller, UART0 console in single-wire mode on PA7 with an optional key that resets the chip into the mask ROM UART loader, GPIO and watchdog reset. - The image runs from RAM; the heap spreads over SRAM, AECRAM and ICRAM. Add the chip documentation: memory map, trap architecture, boot process and the mask ROM's CPU register 0x508. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Alan Carvalho de Assis <[email protected]> --- Documentation/platforms/risc-v/ab32vg1/index.rst | 113 ++++ arch/risc-v/Kconfig | 35 ++ arch/risc-v/include/ab32vg1/chip.h | 47 ++ arch/risc-v/include/ab32vg1/irq.h | 170 ++++++ arch/risc-v/include/irq.h | 6 +- arch/risc-v/include/syscall.h | 24 +- arch/risc-v/src/ab32vg1/CMakeLists.txt | 41 ++ arch/risc-v/src/ab32vg1/Kconfig | 39 ++ arch/risc-v/src/ab32vg1/Make.defs | 33 ++ arch/risc-v/src/ab32vg1/ab32vg1.h | 116 ++++ arch/risc-v/src/ab32vg1/ab32vg1_allocateheap.c | 133 +++++ arch/risc-v/src/ab32vg1/ab32vg1_clockconfig.c | 111 ++++ arch/risc-v/src/ab32vg1/ab32vg1_gpio.c | 155 +++++ arch/risc-v/src/ab32vg1/ab32vg1_gpio.h | 116 ++++ arch/risc-v/src/ab32vg1/ab32vg1_head.S | 297 ++++++++++ arch/risc-v/src/ab32vg1/ab32vg1_idle.c | 61 ++ arch/risc-v/src/ab32vg1/ab32vg1_irq.c | 226 ++++++++ arch/risc-v/src/ab32vg1/ab32vg1_lowputc.c | 142 +++++ arch/risc-v/src/ab32vg1/ab32vg1_lowputc.h | 51 ++ arch/risc-v/src/ab32vg1/ab32vg1_serial.c | 631 +++++++++++++++++++++ arch/risc-v/src/ab32vg1/ab32vg1_start.c | 108 ++++ arch/risc-v/src/ab32vg1/ab32vg1_systemreset.c | 54 ++ arch/risc-v/src/ab32vg1/ab32vg1_timerisr.c | 95 ++++ arch/risc-v/src/ab32vg1/chip.h | 38 ++ arch/risc-v/src/ab32vg1/hardware/ab32vg1_clk.h | 112 ++++ arch/risc-v/src/ab32vg1/hardware/ab32vg1_gpio.h | 81 +++ .../src/ab32vg1/hardware/ab32vg1_memorymap.h | 47 ++ arch/risc-v/src/ab32vg1/hardware/ab32vg1_pic.h | 70 +++ arch/risc-v/src/ab32vg1/hardware/ab32vg1_timer.h | 66 +++ arch/risc-v/src/ab32vg1/hardware/ab32vg1_uart.h | 76 +++ arch/risc-v/src/common/CMakeLists.txt | 8 +- arch/risc-v/src/common/Make.defs | 12 +- 32 files changed, 3301 insertions(+), 13 deletions(-) diff --git a/Documentation/platforms/risc-v/ab32vg1/index.rst b/Documentation/platforms/risc-v/ab32vg1/index.rst new file mode 100644 index 00000000000..11c8ca41fd0 --- /dev/null +++ b/Documentation/platforms/risc-v/ab32vg1/index.rst @@ -0,0 +1,113 @@ +================ +Bluetrum AB32VG1 +================ + +.. tags:: arch:risc-v, chip:ab32vg1, vendor:bluetrum + +The Bluetrum AB32VG1 (also sold as AB5301A, code name "CRWN") is a Bluetooth +audio SoC with a 32-bit RISC-V core: + +* RV32IMC core, up to 120 MHz (48 MHz by default in NuttX) +* 192 KB of RAM in three blocks: + + ============ =========== ========= ============================== + Name Address Size Use in NuttX + ============ =========== ========= ============================== + SRAM 0x00010000 128 KB image (from 0x12000), heap + AECRAM 0x00050000 30.5 KB libc/mm/driver code, heap + ICRAM 0x00060000 32 KB .bss, idle stack, heap + ============ =========== ========= ============================== + +* 1 MB SPI NOR flash in the package (SPI0, port G) +* 3 UARTs, 6 timers, GPIO, RTC, watchdog, SD host, USB, audio codec, FM + radio, Bluetooth + +There is no public reference manual for the CPU core and interrupt +controller. The `register manual +<https://github.com/BLUETRUM/AB32VG1_DOC>`_ covers most peripherals; the +rest of the information used by this port comes from the RT-Thread BSP +(``bsp/bluetrum``) and from experiments on the hardware, documented below. + +Core and interrupts +=================== + +The core implements the RISC-V unprivileged ISA (RV32IMC) but **not** the +standard machine-mode trap architecture: + +* There are no CSRs. Any CSR instruction (including ``rdcycle``), ``ecall`` + or ``ebreak`` raises an exception, and after an exception the core traps + again on every following instruction. Exceptions are therefore fatal and + the port never executes these instructions (images can be checked with + ``riscv-none-elf-objdump -d nuttx | grep csr``). +* Trap state and interrupt control are memory-mapped registers: ``PICCON`` + (bit 0: interrupt enable, bit 1: controller enable), ``PICEN`` (one enable + bit per source), ``PICPR`` (priority), ``PICADR`` (vector table base), + ``PICPND`` (pending), ``EPC`` and ``EPICCON`` (``PICCON.IE`` saved on + trap). +* The vector table has fixed offsets from ``PICADR``: +0x10 exceptions and + high priority interrupts, +0x40 low priority interrupts, +0x80 XIP cache + misses. NuttX uses low priority interrupts only. +* ``mret`` returns to ``EPC`` and restores ``PICCON.IE`` from ``EPICCON``; + this also works outside of a trap. Low priority interrupts do not nest. + +The chip selects ``CONFIG_ARCH_RV_CUSTOM_TRAP``, which lets a chip replace +the CSR-based parts of the common RISC-V code: ``up_irq_save()`` and +``up_irq_restore()`` operate on ``PICCON``, and system calls (used for +context switches) use a *software trap*: ``sys_callN()`` calls +``ab32vg1_syscall_trap()``, which builds the same register frame as a +hardware trap with interrupts masked, dispatches it like an ``ecall`` and +returns through the common trap exit (``EPC``/``EPICCON`` + ``mret``). + +Memory and boot +=============== + +Code normally runs from RAM. The mask ROM can execute from flash through a +software-managed instruction cache (that is how RT-Thread runs), but every +interrupt handler and everything it calls must then live in RAM, which does +not suit NuttX. NuttX is therefore loaded into RAM entirely: + +* by the mask ROM UART loader, for development (``ab32vg1_dl run``), or +* from flash by a small stage-1 loader started by the mask ROM + (``ab32vg1_dl flash``). + +The mask ROM copies the boot code named by the boot header of the flash +(scrambled, CRC-checked) to RAM and calls it. The boot code must clear CPU +register 0x508 early: otherwise the mask ROM takes control back, into its +UART loader, some tens of milliseconds later. That is also the only way +the UART loader is reached after a reset once a boot header is present, so +boot code must listen for the host before clearing 0x508 (see the board +documentation). + +The ROM loader can only write SRAM up to 0x2e800 (it keeps its own data +above), so the image is split: code of the C library, memory manager and +drivers goes to AECRAM, ``.bss`` and the idle stack to ICRAM. The heap uses +all remaining RAM (about 72 KB with the ``nsh`` configuration). + +Supported Peripherals +===================== + +========== ======= ===================================================== +Peripheral Support Notes +========== ======= ===================================================== +Clock Yes PLL0 (240 MHz) / n, ``CONFIG_AB32VG1_SYSCLK_MHZ`` +Timer 0 Yes System tick +UART0 Yes Single-wire on PA7, console +GPIO Yes No pin interrupts yet +Watchdog Reset Used for ``up_systemreset()`` +Flash Tools Programmed by ``ab32vg1_dl``, no MTD driver yet +UART1/2 No +SPI, I2C No +RTC No +SD No +USB No +Audio, BT No +========== ======= ===================================================== + +Supported Boards +================ + +.. toctree:: + :glob: + :maxdepth: 1 + + boards/*/* diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 9f62fa15d4c..07d04614435 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -69,6 +69,19 @@ config ARCH_CHIP_GD32VW55X GigaDevice GD32VW55x Wi-Fi/BLE SoC (Nuclei N307 rv32imafc, ECLIC interrupt controller, 160 MHz, 320 KB SRAM). +config ARCH_CHIP_AB32VG1 + bool "Bluetrum AB32VG1" + select ARCH_RV32 + select ARCH_RV_ISA_M + select ARCH_RV_ISA_C + select ARCH_RV_CUSTOM_TRAP + select ARCH_HAVE_RESET + select ARCH_IDLE_CUSTOM + select LIBC_ATOMIC_IRQ + ---help--- + Bluetrum AB32VG1 (AB5301A, "CRWN") Bluetooth audio SoC with a + rv32imc core, 192 KB SRAM and 1 MB SPI flash. + config ARCH_CHIP_BL602 bool "BouffaloLab BL602" select ARCH_RV32 @@ -716,6 +729,7 @@ config ARCH_CHIP default "k210" if ARCH_CHIP_K210 default "litex" if ARCH_CHIP_LITEX default "gd32vw55x" if ARCH_CHIP_GD32VW55X + default "ab32vg1" if ARCH_CHIP_AB32VG1 default "bl602" if ARCH_CHIP_BL602 default "esp32c3-legacy" if ARCH_CHIP_ESP32C3_LEGACY default "esp32c2" if ARCH_CHIP_ESP32C2 @@ -829,6 +843,24 @@ config ARCH_RV_HAVE_APLIC Controller (APLIC) to provide flexible interrupt control. This device is not backward compatible with PLIC. +config ARCH_RV_CUSTOM_TRAP + bool + default n + ---help--- + Selected by chips whose core implements the RISC-V unprivileged ISA + but not the standard machine-mode trap architecture: there are no + mstatus/mtvec/mepc/mcause CSRs and ecall does not trap. The chip + then provides: + + - up_irq_save() and up_irq_restore() in <arch/chip/irq.h>. + - RISCV_SYSCALL_INSN in <arch/chip/irq.h>: the instruction that + sys_callN() uses instead of ecall. It must trap synchronously + with interrupts masked and be dispatched as RISCV_IRQ_ECALLM. + - The trap entry, riscv_get_newintctx(), riscv_set_idleintctx() and + up_saveusercontext(); the common versions are not built. The + saved REG_INT_CTX must use the mstatus bits (STATUS_PIE, + STATUS_PPP) so that the common code can keep using them. + config ARCH_RV_HAVE_CLIC bool default n @@ -962,6 +994,9 @@ endif if ARCH_CHIP_GD32VW55X source "arch/risc-v/src/gd32vw55x/Kconfig" endif +if ARCH_CHIP_AB32VG1 +source "arch/risc-v/src/ab32vg1/Kconfig" +endif if ARCH_CHIP_BL602 source "arch/risc-v/src/bl602/Kconfig" endif diff --git a/arch/risc-v/include/ab32vg1/chip.h b/arch/risc-v/include/ab32vg1/chip.h new file mode 100644 index 00000000000..4779b0493d1 --- /dev/null +++ b/arch/risc-v/include/ab32vg1/chip.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * arch/risc-v/include/ab32vg1/chip.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_INCLUDE_AB32VG1_CHIP_H +#define __ARCH_RISCV_INCLUDE_AB32VG1_CHIP_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Memory map (AB32VG1 datasheet, "Memory mapping"): + * + * 0x00000000 - 0x00000fff SFR space (accessed with x0-relative loads) + * 0x00010000 - 0x0002ffff SRAM0..3, 128 KB + * 0x00050000 - 0x000579ff AECRAM/DECRAM/ENCRAM, 30.5 KB + * 0x00060000 - 0x00067fff ICRAM (XIP cache lines), 32 KB + * 0x00080000 - ... Mask ROM + * 0x10000000 - 0x100fffff SPI flash window (software-cached XIP) + */ + +#define AB32VG1_SRAM_BASE 0x00010000 +#define AB32VG1_SRAM_SIZE 0x00020000 +#define AB32VG1_AECRAM_BASE 0x00050000 +#define AB32VG1_AECRAM_SIZE 0x00007a00 +#define AB32VG1_ICRAM_BASE 0x00060000 +#define AB32VG1_ICRAM_SIZE 0x00008000 + +#endif /* __ARCH_RISCV_INCLUDE_AB32VG1_CHIP_H */ diff --git a/arch/risc-v/include/ab32vg1/irq.h b/arch/risc-v/include/ab32vg1/irq.h new file mode 100644 index 00000000000..66fc3423ca8 --- /dev/null +++ b/arch/risc-v/include/ab32vg1/irq.h @@ -0,0 +1,170 @@ +/**************************************************************************** + * arch/risc-v/include/ab32vg1/irq.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* The AB32VG1 core implements RV32IMC but not the standard machine-mode + * trap architecture (CONFIG_ARCH_RV_CUSTOM_TRAP): + * + * - There are no CSRs. Any CSR access, ecall or ebreak raises an + * exception which leaves the core in a state where every following + * instruction traps again, so these instructions must never be used. + * - Interrupt masking is bit 0 of the memory-mapped PICCON register. On + * trap entry the previous value is saved in EPICCON and mret restores it. + * + * System calls therefore use a software trap: RISCV_SYSCALL_INSN calls + * ab32vg1_syscall_trap(), which builds the same register frame as a + * hardware trap with interrupts masked, dispatches it as RISCV_IRQ_ECALLM + * and leaves through the common trap exit (EPC/EPICCON + mret), which also + * works from thread mode. ra is preserved on the stack so that the + * instruction sequence does not clobber any register. + */ + +#ifndef __ARCH_RISCV_INCLUDE_AB32VG1_IRQ_H +#define __ARCH_RISCV_INCLUDE_AB32VG1_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#ifndef __ASSEMBLY__ +# include <sys/types.h> +# include <nuttx/compiler.h> +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The AB32VG1 interrupt controller (PIC) has one enable/pending bit per + * source. Several peripherals share a source. NuttX IRQ numbers follow + * the RISC-V exception numbers (0..RISCV_MAX_EXCEPTION). + */ + +#define AB32VG1_IRQ_FIRST RISCV_IRQ_ASYNC + +#define AB32VG1_IRQ_SW (AB32VG1_IRQ_FIRST + 2) /* Software */ +#define AB32VG1_IRQ_TMR0 (AB32VG1_IRQ_FIRST + 3) /* Timer 0 */ +#define AB32VG1_IRQ_TMR1 (AB32VG1_IRQ_FIRST + 4) /* Timer 1 */ +#define AB32VG1_IRQ_TMR245 (AB32VG1_IRQ_FIRST + 5) /* Timer 2, 4, 5 */ +#define AB32VG1_IRQ_IRRX (AB32VG1_IRQ_FIRST + 6) /* Timer 3, IR rx */ +#define AB32VG1_IRQ_USB (AB32VG1_IRQ_FIRST + 7) /* USB */ +#define AB32VG1_IRQ_SD (AB32VG1_IRQ_FIRST + 8) /* SD host */ +#define AB32VG1_IRQ_AUBUF (AB32VG1_IRQ_FIRST + 9) /* Audio buffer 0/1 */ +#define AB32VG1_IRQ_SDADC (AB32VG1_IRQ_FIRST + 10) /* SD ADC */ +#define AB32VG1_IRQ_AUDEC (AB32VG1_IRQ_FIRST + 11) /* Audio codec */ +#define AB32VG1_IRQ_SRC (AB32VG1_IRQ_FIRST + 12) /* SRC, PLC, CVSD */ +#define AB32VG1_IRQ_FM (AB32VG1_IRQ_FIRST + 13) /* FM TX/RX, SPDIF */ +#define AB32VG1_IRQ_UART (AB32VG1_IRQ_FIRST + 14) /* UART 0, 1, 2 */ +#define AB32VG1_IRQ_HSUART (AB32VG1_IRQ_FIRST + 15) /* High speed UART */ +#define AB32VG1_IRQ_RTC (AB32VG1_IRQ_FIRST + 16) /* RTC, LVD, WDT */ +#define AB32VG1_IRQ_I2S (AB32VG1_IRQ_FIRST + 17) /* I2S */ +#define AB32VG1_IRQ_GPIO (AB32VG1_IRQ_FIRST + 18) /* Port interrupt */ + +#define AB32VG1_NPIC_IRQS 23 + +#define NR_IRQS (AB32VG1_IRQ_FIRST + AB32VG1_NPIC_IRQS) + +/* Interrupt controller registers used by the inline functions below */ + +#define AB32VG1_PICCONCLR_ADDR 0x00000530 +#define AB32VG1_PICCONSET_ADDR 0x00000534 +#define AB32VG1_PICCON_ADDR 0x00000540 +#define AB32VG1_PICCON_IE (1 << 0) + +/* Software trap used by sys_callN() in place of ecall */ + +#define RISCV_SYSCALL_INSN \ + "addi sp, sp, -16\n" \ + "sw ra, 0(sp)\n" \ + "jal ra, ab32vg1_syscall_trap\n" \ + "lw ra, 0(sp)\n" \ + "addi sp, sp, 16\n" + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irq_save + * + * Description: + * Disable interrupts and return the previous interrupt enable state. + * + ****************************************************************************/ + +noinstrument_function static inline_function irqstate_t up_irq_save(void) +{ + irqstate_t flags; + + /* The SFRs are below 4 KB: address them relative to x0 */ + + __asm__ __volatile__ + ( + "lw %0, %1(zero)\n" + "sw %2, %3(zero)\n" + : "=&r" (flags) + : "i" (AB32VG1_PICCON_ADDR), "r" (AB32VG1_PICCON_IE), + "i" (AB32VG1_PICCONCLR_ADDR) + : "memory" + ); + + return flags & AB32VG1_PICCON_IE; +} + +/**************************************************************************** + * Name: up_irq_restore + * + * Description: + * Restore the interrupt enable state returned by up_irq_save(). + * + ****************************************************************************/ + +noinstrument_function static inline_function +void up_irq_restore(irqstate_t flags) +{ + if (flags & AB32VG1_PICCON_IE) + { + __asm__ __volatile__ + ( + "sw %0, %1(zero)\n" + : + : "r" (AB32VG1_PICCON_IE), "i" (AB32VG1_PICCONSET_ADDR) + : "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "sw %0, %1(zero)\n" + : + : "r" (AB32VG1_PICCON_IE), "i" (AB32VG1_PICCONCLR_ADDR) + : "memory" + ); + } +} + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_INCLUDE_AB32VG1_IRQ_H */ diff --git a/arch/risc-v/include/irq.h b/arch/risc-v/include/irq.h index f631f7ab71a..3794009d3bf 100644 --- a/arch/risc-v/include/irq.h +++ b/arch/risc-v/include/irq.h @@ -802,7 +802,11 @@ int up_this_cpu(void); * Inline Functions ****************************************************************************/ -#ifdef CONFIG_ARCH_RV_HAVE_CLIC +#if defined(CONFIG_ARCH_RV_CUSTOM_TRAP) + +/* up_irq_save() and up_irq_restore() are provided by <arch/chip/irq.h> */ + +#elif defined(CONFIG_ARCH_RV_HAVE_CLIC) /**************************************************************************** * Name: up_irq_save diff --git a/arch/risc-v/include/syscall.h b/arch/risc-v/include/syscall.h index d81f6684d05..2089341febb 100644 --- a/arch/risc-v/include/syscall.h +++ b/arch/risc-v/include/syscall.h @@ -150,6 +150,16 @@ uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, * in; otherwise there is no fp-chain consumer to fix up for. */ +/* The instruction that enters the kernel. Cores without the standard trap + * architecture (CONFIG_ARCH_RV_CUSTOM_TRAP) provide their own. + */ + +#ifdef CONFIG_ARCH_RV_CUSTOM_TRAP +# include <arch/chip/irq.h> +#else +# define RISCV_SYSCALL_INSN "ecall" +#endif + #if defined(CONFIG_FRAME_POINTER) && defined(CONFIG_SCHED_BACKTRACE) # define RISCV_ECALL_CLOBBERS "memory", "ra" #else @@ -170,7 +180,7 @@ static inline uintptr_t sys_call0(unsigned int nbr) asm volatile ( - "ecall" + RISCV_SYSCALL_INSN :: "r"(r0) : RISCV_ECALL_CLOBBERS ); @@ -195,7 +205,7 @@ static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1) asm volatile ( - "ecall" + RISCV_SYSCALL_INSN :: "r"(r0), "r"(r1) : RISCV_ECALL_CLOBBERS ); @@ -222,7 +232,7 @@ static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, asm volatile ( - "ecall" + RISCV_SYSCALL_INSN :: "r"(r0), "r"(r1), "r"(r2) : RISCV_ECALL_CLOBBERS ); @@ -250,7 +260,7 @@ static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, asm volatile ( - "ecall" + RISCV_SYSCALL_INSN :: "r"(r0), "r"(r1), "r"(r2), "r"(r3) : RISCV_ECALL_CLOBBERS ); @@ -280,7 +290,7 @@ static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, asm volatile ( - "ecall" + RISCV_SYSCALL_INSN :: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4) : RISCV_ECALL_CLOBBERS ); @@ -311,7 +321,7 @@ static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, asm volatile ( - "ecall" + RISCV_SYSCALL_INSN :: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5) : RISCV_ECALL_CLOBBERS ); @@ -344,7 +354,7 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, asm volatile ( - "ecall" + RISCV_SYSCALL_INSN :: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5), "r"(r6) : RISCV_ECALL_CLOBBERS ); diff --git a/arch/risc-v/src/ab32vg1/CMakeLists.txt b/arch/risc-v/src/ab32vg1/CMakeLists.txt new file mode 100644 index 00000000000..11f13dd9c60 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/CMakeLists.txt @@ -0,0 +1,41 @@ +# ############################################################################## +# arch/risc-v/src/ab32vg1/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +# Specify our HEAD assembly file. This will be linked as the first object file, +# so it will appear at address 0 + +list( + APPEND + SRCS + ab32vg1_head.S + ab32vg1_allocateheap.c + ab32vg1_clockconfig.c + ab32vg1_gpio.c + ab32vg1_idle.c + ab32vg1_irq.c + ab32vg1_lowputc.c + ab32vg1_serial.c + ab32vg1_start.c + ab32vg1_systemreset.c + ab32vg1_timerisr.c) + +target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/risc-v/src/ab32vg1/Kconfig b/arch/risc-v/src/ab32vg1/Kconfig new file mode 100644 index 00000000000..6f3cc51ae66 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/Kconfig @@ -0,0 +1,39 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +comment "AB32VG1 Configuration Options" + +config AB32VG1_SYSCLK_MHZ + int "System clock frequency (MHz)" + default 48 + range 24 120 + ---help--- + The system clock is PLL0 (240 MHz) divided by an integer, so the + valid values are 24, 30, 40, 48, 60, 80 and 120. 48 MHz is the + frequency used by the mask ROM and by the RT-Thread BSP. + +menu "AB32VG1 Peripheral Support" + +config AB32VG1_UART0 + bool "UART0" + default y + select UART0_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + ---help--- + UART0 in single-wire mode on PA7 (TX0 group G1, RX mapped to the + TX pin). On the AB32VG1 development boards this is the pin wired + to the USB-serial bridge and used by the mask ROM UART loader. + +config AB32VG1_UART0_ROMKEY + bool "Reboot into the ROM loader on the download key" + default y + depends on AB32VG1_UART0 + ---help--- + Watch the UART0 receive stream for the key sent by host download + tools (F5 A0 A5 96 87 5A) and reset the chip when it is seen, so + that the mask ROM UART loader can take over without pressing the + reset button. + +endmenu diff --git a/arch/risc-v/src/ab32vg1/Make.defs b/arch/risc-v/src/ab32vg1/Make.defs new file mode 100644 index 00000000000..d9abd4c1ac5 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/Make.defs @@ -0,0 +1,33 @@ +############################################################################ +# arch/risc-v/src/ab32vg1/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include common/Make.defs + +# Specify our HEAD assembly file. This will be linked as +# the first object file, so it will appear at address 0 +HEAD_ASRC = ab32vg1_head.S + +# Specify our C code within this directory to be included +CHIP_CSRCS = ab32vg1_allocateheap.c ab32vg1_clockconfig.c ab32vg1_gpio.c +CHIP_CSRCS += ab32vg1_idle.c +CHIP_CSRCS += ab32vg1_irq.c ab32vg1_lowputc.c ab32vg1_serial.c +CHIP_CSRCS += ab32vg1_start.c ab32vg1_systemreset.c ab32vg1_timerisr.c diff --git a/arch/risc-v/src/ab32vg1/ab32vg1.h b/arch/risc-v/src/ab32vg1/ab32vg1.h new file mode 100644 index 00000000000..e2e74ba2c38 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1.h @@ -0,0 +1,116 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_AB32VG1_AB32VG1_H +#define __ARCH_RISCV_SRC_AB32VG1_AB32VG1_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include "riscv_common_memorymap.h" + +#ifndef __ASSEMBLY__ +# include <stdint.h> +# include "riscv_internal.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The idle thread stack starts at _ebss */ + +#ifndef __ASSEMBLY__ +# define AB32VG1_IDLESTACK_BASE (uintptr_t)_ebss +#else +# define AB32VG1_IDLESTACK_BASE _ebss +#endif + +#define AB32VG1_IDLESTACK_TOP (AB32VG1_IDLESTACK_BASE + SMP_STACK_SIZE) + +/* Symbols that the board linker script must provide, in addition to the + * common ones (_stext, _sbss, _ebss, ...): the end of the image in SRAM and + * the end of the code placed in AECRAM. + */ + +#ifndef __ASSEMBLY__ +extern uint8_t _esram[]; +extern uint8_t _eaecram[]; +#endif + +/* System clock */ + +#define AB32VG1_SYSCLK_FREQUENCY (CONFIG_AB32VG1_SYSCLK_MHZ * 1000000) + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ab32vg1_clockconfig + * + * Description: + * Switch the system clock to PLL0 / n (CONFIG_AB32VG1_SYSCLK_MHZ). + * + ****************************************************************************/ + +void ab32vg1_clockconfig(void); + +/**************************************************************************** + * Name: ab32vg1_lowsetup + * + * Description: + * Configure the console UART for polled output, early in the boot. + * + ****************************************************************************/ + +void ab32vg1_lowsetup(void); + +/**************************************************************************** + * Name: ab32vg1_boardinitialize + * + * Description: + * Board-specific early initialization, provided by the board logic. + * + ****************************************************************************/ + +void ab32vg1_boardinitialize(void); + +/**************************************************************************** + * Name: ab32vg1_dispatch_trap + * + * Description: + * Called from the trap entry code with the trap kind (0 exception, + * 1 interrupt, 2 system call) and the saved registers. Returns the + * register frame to restore. + * + ****************************************************************************/ + +uintreg_t *ab32vg1_dispatch_trap(int kind, uintreg_t *regs); + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_AB32VG1_AB32VG1_H */ diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_allocateheap.c b/arch/risc-v/src/ab32vg1/ab32vg1_allocateheap.c new file mode 100644 index 00000000000..aa640c985ca --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_allocateheap.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_allocateheap.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <assert.h> + +#include <nuttx/arch.h> +#include <nuttx/board.h> +#include <nuttx/kmalloc.h> +#include <arch/board/board.h> + +#include "riscv_internal.h" +#include "chip.h" +#include "ab32vg1.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Memory layout (see the board linker script): + * + * SRAM 0x10000 .. _stext free (ROM scratch during boot) + * SRAM _stext .. _esram image, loaded by the ROM or boot code + * SRAM _esram .. 0x30000 free + * AECRAM 0x50000 .. _eaecram code placed in AECRAM (C library) + * AECRAM _eaecram.. 0x57a00 free + * ICRAM 0x60000 .. _ebss .bss + * ICRAM _ebss .. idle top idle thread stack + * ICRAM idle top.. 0x68000 free + * + * The primary heap is SRAM after the image; the other free chunks are added + * as extra regions up to CONFIG_MM_REGIONS. + */ + +#define HEAP_ALIGN(a) (((uintptr_t)(a) + 15) & ~(uintptr_t)15) + +#define SRAM_END (AB32VG1_SRAM_BASE + AB32VG1_SRAM_SIZE) +#define AECRAM_END (AB32VG1_AECRAM_BASE + AB32VG1_AECRAM_SIZE) +#define ICRAM_END (AB32VG1_ICRAM_BASE + AB32VG1_ICRAM_SIZE) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if CONFIG_MM_REGIONS > 1 +static void ab32vg1_addchunk(uintptr_t start, uintptr_t end) +{ + start = HEAP_ALIGN(start); + if (start + 64 < end) + { + kumm_addregion((void *)start, end - start); + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_heap + * + * Description: + * Return the primary heap: SRAM between the end of the image and the end + * of SRAM. + * + ****************************************************************************/ + +void up_allocate_heap(void **heap_start, size_t *heap_size) +{ + uintptr_t start = HEAP_ALIGN(_esram); + + DEBUGASSERT(start < SRAM_END); + + board_autoled_on(LED_HEAPALLOCATE); + *heap_start = (void *)start; + *heap_size = SRAM_END - start; +} + +/**************************************************************************** + * Name: riscv_addregion + * + * Description: + * RAM may be added in non-contiguous chunks. This routine adds all chunks + * that may be used for heap. + * + ****************************************************************************/ + +#if CONFIG_MM_REGIONS > 1 +void riscv_addregion(void) +{ + /* ICRAM after .bss and the idle stack */ + + ab32vg1_addchunk(g_idle_topstack, ICRAM_END); + +#if CONFIG_MM_REGIONS > 2 + /* AECRAM after the code placed there */ + + ab32vg1_addchunk((uintptr_t)_eaecram, AECRAM_END); +#endif + +#if CONFIG_MM_REGIONS > 3 + /* SRAM below the image */ + + ab32vg1_addchunk(AB32VG1_SRAM_BASE, (uintptr_t)_stext); +#endif +} +#endif diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_clockconfig.c b/arch/risc-v/src/ab32vg1/ab32vg1_clockconfig.c new file mode 100644 index 00000000000..bbd9d263d8e --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_clockconfig.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_clockconfig.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> + +#include "riscv_internal.h" +#include "chip.h" +#include "ab32vg1.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* System clock = PLL0 (240 MHz) / (SPLLDIV + 1) */ + +#define SPLL_DIV (AB32VG1_PLL0_FREQUENCY / AB32VG1_SYSCLK_FREQUENCY - 1) + +#if (AB32VG1_PLL0_FREQUENCY % AB32VG1_SYSCLK_FREQUENCY) != 0 +# error CONFIG_AB32VG1_SYSCLK_MHZ must divide 240 MHz +#endif + +/* The internal SPI flash clock must stay at or below 24 MHz: + * SPI0BAUD = sysclk / 24 MHz, rounded up, minus 1. + */ + +#define SPI0_BAUD ((AB32VG1_SYSCLK_FREQUENCY + 23999999) / 24000000 - 1) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void ab32vg1_busywait(volatile uint32_t loops) +{ + while (loops-- > 0) + { + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ab32vg1_clockconfig + * + * Description: + * Switch the system clock to PLL0 / n. Follows set_sysclk() from the + * RT-Thread AB32VG1 BSP (system_ab32vgx.c, Apache-2.0). Must run before + * interrupts are enabled. + * + ****************************************************************************/ + +void ab32vg1_clockconfig(void) +{ + /* Start PLL0 at 240 MHz if the boot code did not */ + + if ((getreg32(AB32VG1_PLL0CON) & PLL0CON_LDO_EN) == 0) + { + modifyreg32(AB32VG1_PLL0CON, PLL0CON_VCO_MASK, PLL0CON_VCO_HIGH); + modifyreg32(AB32VG1_PLL0CON, 0, PLL0CON_LDO_EN); + ab32vg1_busywait(1000); /* >= 100 us */ + putreg32(AB32VG1_PLL0DIV_240M, AB32VG1_PLL0DIV); + modifyreg32(AB32VG1_PLL0CON, 0, PLL0CON_DIV_UPDATE); + modifyreg32(AB32VG1_PLL0CON, 0, PLL0CON_ANALOG_EN); + modifyreg32(AB32VG1_PLL0CON, 0, PLL0CON_SDM_EN); + ab32vg1_busywait(10000); /* >= 1 ms to lock */ + } + + /* Run from the 2 MHz RC oscillator while the dividers change */ + + modifyreg32(AB32VG1_CLKCON0, CLKCON0_SYSCLK_MASK, CLKCON0_SYSCLK_RC2M); + modifyreg32(AB32VG1_CLKCON2, CLKCON2_SPLLDIV_MASK, 0); + modifyreg32(AB32VG1_CLKCON0, CLKCON0_SPLL_MASK, CLKCON0_SPLL_PLL0); + + if (getreg32(AB32VG1_PLL0DIV) != AB32VG1_PLL0DIV_240M) + { + putreg32(AB32VG1_PLL0DIV_240M, AB32VG1_PLL0DIV); + modifyreg32(AB32VG1_PLL0CON, PLL0CON_VCO_MASK, PLL0CON_VCO_HIGH); + modifyreg32(AB32VG1_PLL0CON, 0, PLL0CON_DIV_UPDATE); + } + + modifyreg32(AB32VG1_CLKCON2, CLKCON2_SPLLDIV_MASK, + SPLL_DIV << CLKCON2_SPLLDIV_SHIFT); + putreg32(SPI0_BAUD, AB32VG1_SPI0BAUD); + modifyreg32(AB32VG1_CLKCON0, CLKCON0_SYSCLK_MASK, CLKCON0_SYSCLK_SPLL); +} diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_gpio.c b/arch/risc-v/src/ab32vg1/ab32vg1_gpio.c new file mode 100644 index 00000000000..4a03cdc680a --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_gpio.c @@ -0,0 +1,155 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_gpio.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <stdbool.h> +#include <errno.h> + +#include <nuttx/irq.h> +#include <arch/irq.h> + +#include "riscv_internal.h" +#include "chip.h" +#include "ab32vg1_gpio.h" +#include "hardware/ab32vg1_gpio.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uintptr_t g_portbase[] = +{ + AB32VG1_GPIOA_BASE, + AB32VG1_GPIOB_BASE, + AB32VG1_GPIOE_BASE, + AB32VG1_GPIOF_BASE, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline uintptr_t ab32vg1_portbase(gpio_pinset_t pinset) +{ + return g_portbase[(pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT]; +} + +static inline uint32_t ab32vg1_pinmask(gpio_pinset_t pinset) +{ + return 1 << ((pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ab32vg1_configgpio + ****************************************************************************/ + +int ab32vg1_configgpio(gpio_pinset_t cfgset) +{ + uintptr_t base; + uint32_t mask; + irqstate_t flags; + + if (((cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT) >= 4) + { + return -EINVAL; + } + + base = ab32vg1_portbase(cfgset); + mask = ab32vg1_pinmask(cfgset); + + flags = up_irq_save(); + + /* Digital GPIO function */ + + modifyreg32(base + AB32VG1_GPIO_FEN_OFFSET, mask, 0); + modifyreg32(base + AB32VG1_GPIO_DE_OFFSET, 0, mask); + + /* Pull resistors */ + + modifyreg32(base + AB32VG1_GPIO_PU_OFFSET, mask, 0); + modifyreg32(base + AB32VG1_GPIO_PD_OFFSET, mask, 0); + modifyreg32(base + AB32VG1_GPIO_PU200K_OFFSET, mask, 0); + modifyreg32(base + AB32VG1_GPIO_PD200K_OFFSET, mask, 0); + modifyreg32(base + AB32VG1_GPIO_PU300_OFFSET, mask, 0); + modifyreg32(base + AB32VG1_GPIO_PD300_OFFSET, mask, 0); + + switch (cfgset & GPIO_PULL_MASK) + { + case GPIO_PULLUP: + modifyreg32(base + AB32VG1_GPIO_PU_OFFSET, 0, mask); + break; + + case GPIO_PULLDOWN: + modifyreg32(base + AB32VG1_GPIO_PD_OFFSET, 0, mask); + break; + + default: + break; + } + + /* Direction; set the output level before driving the pin */ + + if (cfgset & GPIO_OUTPUT) + { + putreg32(mask, base + ((cfgset & GPIO_VALUE_ONE) ? + AB32VG1_GPIO_SET_OFFSET : + AB32VG1_GPIO_CLR_OFFSET)); + modifyreg32(base + AB32VG1_GPIO_DIR_OFFSET, mask, 0); + } + else + { + modifyreg32(base + AB32VG1_GPIO_DIR_OFFSET, 0, mask); + } + + up_irq_restore(flags); + return OK; +} + +/**************************************************************************** + * Name: ab32vg1_gpiowrite + ****************************************************************************/ + +void ab32vg1_gpiowrite(gpio_pinset_t pinset, bool value) +{ + putreg32(ab32vg1_pinmask(pinset), ab32vg1_portbase(pinset) + + (value ? AB32VG1_GPIO_SET_OFFSET : AB32VG1_GPIO_CLR_OFFSET)); +} + +/**************************************************************************** + * Name: ab32vg1_gpioread + ****************************************************************************/ + +bool ab32vg1_gpioread(gpio_pinset_t pinset) +{ + return (getreg32(ab32vg1_portbase(pinset) + AB32VG1_GPIO_DATA_OFFSET) & + ab32vg1_pinmask(pinset)) != 0; +} diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_gpio.h b/arch/risc-v/src/ab32vg1/ab32vg1_gpio.h new file mode 100644 index 00000000000..fe7c500929a --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_gpio.h @@ -0,0 +1,116 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_gpio.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_AB32VG1_AB32VG1_GPIO_H +#define __ARCH_RISCV_SRC_AB32VG1_AB32VG1_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <stdbool.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Pin configuration encoding (16 bits): + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ---- ---- ---- ---- + * .... .... .... .PPP Pin number 0..7 + * .... .... ..PP P... Port: A, B, E, F + * .... .... .D.. .... Direction: 1 = output + * .... .... V... .... Initial output value + * .... ..UU .... .... Pull: none, up, down (10 Kohm) + */ + +#define GPIO_PIN_SHIFT 0 +#define GPIO_PIN_MASK (7 << GPIO_PIN_SHIFT) +# define GPIO_PIN(n) ((n) << GPIO_PIN_SHIFT) + +#define GPIO_PORT_SHIFT 3 +#define GPIO_PORT_MASK (7 << GPIO_PORT_SHIFT) +# define GPIO_PORTA (0 << GPIO_PORT_SHIFT) +# define GPIO_PORTB (1 << GPIO_PORT_SHIFT) +# define GPIO_PORTE (2 << GPIO_PORT_SHIFT) +# define GPIO_PORTF (3 << GPIO_PORT_SHIFT) + +#define GPIO_OUTPUT (1 << 6) +#define GPIO_INPUT (0) +#define GPIO_VALUE_ONE (1 << 7) +#define GPIO_VALUE_ZERO (0) + +#define GPIO_PULL_SHIFT 8 +#define GPIO_PULL_MASK (3 << GPIO_PULL_SHIFT) +# define GPIO_FLOAT (0 << GPIO_PULL_SHIFT) +# define GPIO_PULLUP (1 << GPIO_PULL_SHIFT) +# define GPIO_PULLDOWN (2 << GPIO_PULL_SHIFT) + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef uint16_t gpio_pinset_t; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ab32vg1_configgpio + * + * Description: + * Configure a pin as a digital GPIO according to the encoded pinset. + * + ****************************************************************************/ + +int ab32vg1_configgpio(gpio_pinset_t cfgset); + +/**************************************************************************** + * Name: ab32vg1_gpiowrite + * + * Description: + * Drive an output pin. + * + ****************************************************************************/ + +void ab32vg1_gpiowrite(gpio_pinset_t pinset, bool value); + +/**************************************************************************** + * Name: ab32vg1_gpioread + * + * Description: + * Read the level of a pin. + * + ****************************************************************************/ + +bool ab32vg1_gpioread(gpio_pinset_t pinset); + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_AB32VG1_AB32VG1_GPIO_H */ diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_head.S b/arch/risc-v/src/ab32vg1/ab32vg1_head.S new file mode 100644 index 00000000000..385657289d6 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_head.S @@ -0,0 +1,297 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_head.S + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <arch/irq.h> +#include <arch/mode.h> + +#include "chip.h" +#include "ab32vg1.h" +#include "riscv_macros.S" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Trap kinds passed to ab32vg1_dispatch_trap() */ + +#define TRAP_EXCEPTION 0 +#define TRAP_IRQ 1 +#define TRAP_SYSCALL 2 + +/* Status word stored in REG_INT_CTX: STATUS_PIE mirrors EPICCON.IE, so the + * common code (signal delivery, swint) can keep using the standard bits. + */ + +#define INTCTX_PIE_SHIFT 7 /* log2(STATUS_PIE) */ + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .global __start + .global ab32vg1_vectors + .global ab32vg1_syscall_trap + .global ab32vg1_trap_return + .global up_saveusercontext + +/**************************************************************************** + * Name: __start + * + * Description: + * Image entry point. The mask ROM UART loader calls the image at its + * load address as a command handler, from the ROM stack at the top of + * SRAM; a boot header loader jumps to it. Never returns. + * + ****************************************************************************/ + + .section .start, "ax" + .type __start, function + +__start: + + /* Mask all interrupts: the ROM leaves its HSUART interrupt enabled */ + + sw zero, AB32VG1_PICEN(zero) + li t0, (PICCON_IE | PICCON_EN) + sw t0, AB32VG1_PICCONCLR(zero) + + /* Install our vector table */ + + la t0, ab32vg1_vectors + sw t0, AB32VG1_PICADR(zero) + + /* Set the stack pointer to the idle thread stack */ + + la sp, AB32VG1_IDLESTACK_TOP + + /* Jump to __ab32vg1_start; it never returns */ + + jal x1, __ab32vg1_start + +1: + j 1b + + .size __start, . - __start + +/**************************************************************************** + * Name: ab32vg1_vectors + * + * Description: + * Vector table pointed by PICADR. Entries are fixed offsets from the + * base: +0x10 exceptions (and high priority interrupts, unused), +0x40 + * low priority interrupts, +0x80 XIP cache miss (unused, the image runs + * from RAM). + * + ****************************************************************************/ + + .section .text.ab32vg1_vectors, "ax" + .balign 1024 + .type ab32vg1_vectors, function + +ab32vg1_vectors: + j exception_entry /* +0x00: not expected */ + .org ab32vg1_vectors + AB32VG1_VEC_EXCEPTION + j exception_entry + .org ab32vg1_vectors + AB32VG1_VEC_IRQ + j irq_entry + .org ab32vg1_vectors + AB32VG1_VEC_CACHE + j exception_entry + + .size ab32vg1_vectors, . - ab32vg1_vectors + +/**************************************************************************** + * Name: trap_entry + * + * Description: + * Save the full context on the current stack and call + * ab32vg1_dispatch_trap(kind, regs). Used by the hardware vectors. + * + ****************************************************************************/ + +.macro trap_entry kind + + addi sp, sp, -XCPTCONTEXT_SIZE + save_ctx sp + + lw s0, AB32VG1_EPICCON(zero) /* Previous interrupt enable */ + andi s0, s0, PICCON_IE + slli s0, s0, INTCTX_PIE_SHIFT + li s1, STATUS_PPP + or s0, s0, s1 + REGSTORE s0, REG_INT_CTX(sp) + + lw s1, AB32VG1_EPC(zero) /* Return address */ + REGSTORE s1, REG_EPC(sp) + + addi s2, sp, XCPTCONTEXT_SIZE /* Interrupted sp */ + REGSTORE s2, REG_SP(sp) + + li a0, \kind + j trap_dispatch + +.endm + + .section .text.ab32vg1_trap, "ax" + +exception_entry: + trap_entry TRAP_EXCEPTION + +irq_entry: + trap_entry TRAP_IRQ + +/**************************************************************************** + * Name: ab32vg1_syscall_trap + * + * Description: + * Software equivalent of ecall, reached through RISCV_SYSCALL_INSN with + * "jal ra, ab32vg1_syscall_trap" (the caller preserves its own ra). + * Builds the same frame as a hardware trap with interrupts masked. The + * saved EPC is ra - 4 because riscv_doirq() advances it by 4, as it does + * for a real ecall. + * + ****************************************************************************/ + + .type ab32vg1_syscall_trap, function + +ab32vg1_syscall_trap: + + addi sp, sp, -XCPTCONTEXT_SIZE + save_ctx sp + + lw s0, AB32VG1_PICCON(zero) /* Current interrupt enable */ + li s1, PICCON_IE + sw s1, AB32VG1_PICCONCLR(zero) /* Mask interrupts */ + andi s0, s0, PICCON_IE + slli s0, s0, INTCTX_PIE_SHIFT + li s1, STATUS_PPP + or s0, s0, s1 + REGSTORE s0, REG_INT_CTX(sp) + + addi s1, ra, -4 + REGSTORE s1, REG_EPC(sp) + + addi s2, sp, XCPTCONTEXT_SIZE + REGSTORE s2, REG_SP(sp) + + li a0, TRAP_SYSCALL + + /* Fall through */ + +/**************************************************************************** + * Name: trap_dispatch + * + * Description: + * a0 = trap kind, sp = register frame. Switch to the interrupt stack, + * call the C dispatcher and return to the context it selects. + * + ****************************************************************************/ + +trap_dispatch: + + mv a1, sp /* a1 = regs */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 15 + setintstack t0, t1 +#endif + + call ab32vg1_dispatch_trap + + /* Fall through with a0 = the register frame to restore */ + +/**************************************************************************** + * Name: ab32vg1_trap_return + * + * Description: + * Restore the context in a0 and return to it. EPC and EPICCON are + * written before mret; interrupts are masked here, either by hardware + * (inside a trap) or by ab32vg1_syscall_trap. + * + ****************************************************************************/ + +ab32vg1_trap_return: + + mv sp, a0 + + REGLOAD s0, REG_EPC(sp) + sw s0, AB32VG1_EPC(zero) + + REGLOAD s0, REG_INT_CTX(sp) + srli s0, s0, INTCTX_PIE_SHIFT + andi s0, s0, PICCON_IE + sw s0, AB32VG1_EPICCON(zero) + + load_ctx sp + REGLOAD sp, REG_SP(sp) + + mret + + .size ab32vg1_syscall_trap, . - ab32vg1_syscall_trap + +/**************************************************************************** + * Name: up_saveusercontext + * + * Description: + * Save the current register context (used by the assertion logic). + * + ****************************************************************************/ + + .type up_saveusercontext, function + +up_saveusercontext: + + save_ctx a0 + + lw a1, AB32VG1_PICCON(zero) + andi a1, a1, PICCON_IE + slli a1, a1, INTCTX_PIE_SHIFT + REGSTORE a1, REG_INT_CTX(a0) + + REGSTORE sp, REG_X2(a0) + REGSTORE x1, REG_EPC(a0) + + li a0, 0 + ret + + .size up_saveusercontext, . - up_saveusercontext + +/**************************************************************************** + * Name: g_intstackalloc and g_intstacktop + ****************************************************************************/ + +#if CONFIG_ARCH_INTERRUPTSTACK > 15 + .bss + .balign 16 + .global g_intstackalloc + .global g_intstacktop + .type g_intstackalloc, object + .type g_intstacktop, object +g_intstackalloc: + .skip STACKFRAME_ALIGN_UP(INT_STACK_SIZE) +g_intstacktop: + .size g_intstacktop, 0 + .size g_intstackalloc, STACKFRAME_ALIGN_DOWN(INT_STACK_SIZE) +#endif diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_idle.c b/arch/risc-v/src/ab32vg1/ab32vg1_idle.c new file mode 100644 index 00000000000..41ac0002d5a --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_idle.c @@ -0,0 +1,61 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_idle.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/arch.h> +#include <nuttx/board.h> +#include <arch/board/board.h> + +#include "riscv_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when there is no other + * ready-to-run task. This is processor idle time and will continue until + * some interrupt occurs to cause a context switch from the idle task. + * + * The AB32VG1 core has no standard wfi (system instructions trap and the + * core cannot recover from that), so the idle loop simply spins. + * + ****************************************************************************/ + +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, then process + * "fake" timer interrupts. Hopefully, something will wake up. + */ + + nxsched_process_timer(); +#endif +} diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_irq.c b/arch/risc-v/src/ab32vg1/ab32vg1_irq.c new file mode 100644 index 00000000000..db080f94817 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_irq.c @@ -0,0 +1,226 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_irq.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <inttypes.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/arch.h> +#include <nuttx/irq.h> +#include <nuttx/board.h> +#include <arch/irq.h> +#include <arch/board/board.h> + +#include "riscv_internal.h" +#include "chip.h" +#include "ab32vg1.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define TRAP_EXCEPTION 0 +#define TRAP_IRQ 1 +#define TRAP_SYSCALL 2 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ab32vg1_exception + * + * Description: + * Fatal trap: illegal instruction, CSR access, ecall, ebreak or a + * spurious XIP cache miss. The core does not report the cause and + * cannot resume after an exception (it keeps trapping on every + * instruction), so this never returns. + * + ****************************************************************************/ + +static void ab32vg1_exception(uintreg_t *regs) +{ + _alert("EXCEPTION: EPC: %08" PRIxREG " (address after the faulting " + "instruction) CPU status: %08" PRIx32 "\n", + regs[REG_EPC], getreg32(AB32VG1_CPU_STATUS)); + + up_set_interrupt_context(true); + PANIC_WITH_REGS("panic", regs); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ab32vg1_dispatch_trap + ****************************************************************************/ + +uintreg_t *ab32vg1_dispatch_trap(int kind, uintreg_t *regs) +{ + uint32_t pending; + int bit; + + switch (kind) + { + case TRAP_SYSCALL: + return riscv_doirq(RISCV_IRQ_ECALLM, regs); + + case TRAP_IRQ: + + /* Dispatch one source per trap: riscv_doirq() may switch context. + * Remaining sources trap again right after mret. + */ + + pending = getreg32(AB32VG1_PICPND) & getreg32(AB32VG1_PICEN); + if (pending == 0) + { + return regs; + } + + bit = __builtin_ctz(pending); + if (bit == AB32VG1_IRQ_SW - AB32VG1_IRQ_FIRST) + { + putreg32(1 << bit, AB32VG1_PICPND); + } + + return riscv_doirq(AB32VG1_IRQ_FIRST + bit, regs); + + default: + ab32vg1_exception(regs); + return regs; + } +} + +/**************************************************************************** + * Name: up_irqinitialize + ****************************************************************************/ + +void up_irqinitialize(void) +{ + /* Disable all sources, all low priority, unit enabled, IE off */ + + up_irq_save(); + putreg32(0, AB32VG1_PICEN); + putreg32(0, AB32VG1_PICPR); + putreg32(0xffffffff, AB32VG1_PICPND); + modifyreg32(AB32VG1_PICCON, PICCON_IE, PICCON_INIT); + + /* Colorize the interrupt stack for debug purposes */ + + riscv_color_intstack(); + + /* The software trap is dispatched as an M-mode ecall */ + + irq_attach(RISCV_IRQ_ECALLM, riscv_swint, NULL); + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + /* And finally, enable interrupts */ + + up_irq_enable(); +#endif +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + irqstate_t flags; + + if (irq >= AB32VG1_IRQ_FIRST && irq < NR_IRQS) + { + flags = up_irq_save(); + modifyreg32(AB32VG1_PICEN, 1 << (irq - AB32VG1_IRQ_FIRST), 0); + up_irq_restore(flags); + } +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + irqstate_t flags; + + if (irq >= AB32VG1_IRQ_FIRST && irq < NR_IRQS) + { + flags = up_irq_save(); + modifyreg32(AB32VG1_PICEN, 0, 1 << (irq - AB32VG1_IRQ_FIRST)); + up_irq_restore(flags); + } +} + +/**************************************************************************** + * Name: up_irq_enable + * + * Description: + * Return the current interrupt state and enable interrupts + * + ****************************************************************************/ + +irqstate_t up_irq_enable(void) +{ + irqstate_t flags = getreg32(AB32VG1_PICCON) & PICCON_IE; + + putreg32(PICCON_IE, AB32VG1_PICCONSET); + return flags; +} + +/**************************************************************************** + * Name: riscv_get_newintctx + * + * Description: + * Return the initial REG_INT_CTX of a new thread: interrupts enabled + * once the thread starts (STATUS_PIE is copied to EPICCON.IE on return). + * + ****************************************************************************/ + +uintptr_t riscv_get_newintctx(void) +{ + return STATUS_PPP | STATUS_PIE; +} + +/**************************************************************************** + * Name: riscv_set_idleintctx + ****************************************************************************/ + +void riscv_set_idleintctx(void) +{ +} diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_lowputc.c b/arch/risc-v/src/ab32vg1/ab32vg1_lowputc.c new file mode 100644 index 00000000000..30c5300039b --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_lowputc.c @@ -0,0 +1,142 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_lowputc.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <stdbool.h> + +#include <arch/board/board.h> + +#include "riscv_internal.h" +#include "chip.h" +#include "ab32vg1.h" +#include "ab32vg1_lowputc.h" +#include "hardware/ab32vg1_uart.h" +#include "hardware/ab32vg1_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_UART0_SERIAL_CONSOLE +# define HAVE_CONSOLE 1 +#endif + +#define UART0_CON (AB32VG1_UART0_BASE + AB32VG1_UART_CON_OFFSET) +#define UART0_CPND (AB32VG1_UART0_BASE + AB32VG1_UART_CPND_OFFSET) +#define UART0_BAUD (AB32VG1_UART0_BASE + AB32VG1_UART_BAUD_OFFSET) +#define UART0_DATA (AB32VG1_UART0_BASE + AB32VG1_UART_DATA_OFFSET) + +/* PA7 is the UART0 TX pin of pin group G1 */ + +#define UART0_PIN (1 << 7) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ab32vg1_uart0_configure + ****************************************************************************/ + +void ab32vg1_uart0_configure(uint32_t baud, bool stop2) +{ + uint32_t div = (UART_INC_FREQUENCY + baud / 2) / baud - 1; + uint32_t con; + + putreg32(0, UART0_CON); + + /* Clocks: uart_inc and the UART0 gate */ + + modifyreg32(AB32VG1_CLKCON1, 0, CLKCON1_UART_INC); + modifyreg32(AB32VG1_CLKGAT0, 0, CLKGAT0_UART0); + + /* PA7: digital input with pull-up, driven by the peripheral */ + + modifyreg32(AB32VG1_GPIOA_BASE + AB32VG1_GPIO_FEN_OFFSET, 0, UART0_PIN); + modifyreg32(AB32VG1_GPIOA_BASE + AB32VG1_GPIO_DE_OFFSET, 0, UART0_PIN); + modifyreg32(AB32VG1_GPIOA_BASE + AB32VG1_GPIO_DIR_OFFSET, 0, UART0_PIN); + modifyreg32(AB32VG1_GPIOA_BASE + AB32VG1_GPIO_PD_OFFSET, UART0_PIN, 0); + modifyreg32(AB32VG1_GPIOA_BASE + AB32VG1_GPIO_PU_OFFSET, 0, UART0_PIN); + + /* TX0 on group G1 (PA7), RX0 on the TX pin */ + + putreg32((FUNCMCON_CLEAR << FUNCMCON0_UT0RXMAP_SHIFT) | + (FUNCMCON_CLEAR << FUNCMCON0_UT0TXMAP_SHIFT), + AB32VG1_FUNCMCON0); + putreg32((FUNCMCON_RX_ON_TX << FUNCMCON0_UT0RXMAP_SHIFT) | + (FUNCMCON_G(1) << FUNCMCON0_UT0TXMAP_SHIFT), + AB32VG1_FUNCMCON0); + + putreg32(UART_BAUD(div), UART0_BAUD); + + con = UART_CON_RXEN | UART_CON_ONELINE | UART_CON_CLKSRC | UART_CON_UTEN; + if (stop2) + { + con |= UART_CON_SB2EN; + } + + putreg32(UART_CPND_CRXPND | UART_CPND_CTXPND, UART0_CPND); + putreg32(con, UART0_CON); +} + +/**************************************************************************** + * Name: riscv_lowputc + * + * Description: + * Output one byte on the serial console. TXPND is set when a byte has + * been shifted out and cleared by writing the data register; it reads 0 + * before the first byte, so wait after writing rather than before. + * + ****************************************************************************/ + +void riscv_lowputc(char ch) +{ +#ifdef HAVE_CONSOLE + putreg32((uint8_t)ch, UART0_DATA); + while ((getreg32(UART0_CON) & UART_CON_TXPND) == 0) + { + } +#endif +} + +/**************************************************************************** + * Name: ab32vg1_lowsetup + * + * Description: + * This performs basic initialization of the UART used for the serial + * console. Its purpose is to get the console output available as soon + * as possible. + * + ****************************************************************************/ + +void ab32vg1_lowsetup(void) +{ +#ifdef HAVE_CONSOLE + ab32vg1_uart0_configure(CONFIG_UART0_BAUD, CONFIG_UART0_2STOP != 0); +#endif +} diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_lowputc.h b/arch/risc-v/src/ab32vg1/ab32vg1_lowputc.h new file mode 100644 index 00000000000..424672c0e15 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_lowputc.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_lowputc.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_AB32VG1_AB32VG1_LOWPUTC_H +#define __ARCH_RISCV_SRC_AB32VG1_AB32VG1_LOWPUTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <stdbool.h> + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ab32vg1_uart0_configure + * + * Description: + * Configure UART0 in single-wire mode on PA7: pin mux, clocks, baud + * rate (clocked from uart_inc = 13 MHz) and frame format. Interrupts + * are left disabled. + * + ****************************************************************************/ + +void ab32vg1_uart0_configure(uint32_t baud, bool stop2); + +#endif /* __ARCH_RISCV_SRC_AB32VG1_AB32VG1_LOWPUTC_H */ diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_serial.c b/arch/risc-v/src/ab32vg1/ab32vg1_serial.c new file mode 100644 index 00000000000..6931b4896f2 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_serial.c @@ -0,0 +1,631 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_serial.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> +#include <stdint.h> +#include <stdbool.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <debug.h> + +#ifdef CONFIG_SERIAL_TERMIOS +# include <termios.h> +#endif + +#include <nuttx/irq.h> +#include <nuttx/arch.h> +#include <nuttx/spinlock.h> +#include <nuttx/serial/serial.h> + +#include <arch/board/board.h> + +#include "riscv_internal.h" +#include "chip.h" +#include "ab32vg1.h" +#include "ab32vg1_lowputc.h" +#include "hardware/ab32vg1_uart.h" + +#ifdef USE_SERIALDRIVER + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_AB32VG1_UART0 +# error "The serial driver requires CONFIG_AB32VG1_UART0" +#endif + +#ifdef CONFIG_UART0_SERIAL_CONSOLE +# define CONSOLE_DEV g_uart0port /* UART0 is console */ +# define HAVE_CONSOLE 1 +#endif + +#define TTYS0_DEV g_uart0port /* UART0 is ttyS0 */ + +/* Key sent by host tools to reach the mask ROM loader: the "reset" token + * followed by the sync token (see scripts/ab32vg1_dl.py). + */ + +#define ROMKEY_LEN 6 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct ab32vg1_uart_s +{ + uintptr_t base; /* Base address of the UART registers */ + uint32_t baud; /* Configured baud */ + int irq; /* PIC interrupt (shared by UART0/1/2) */ + bool stop2; /* Two stop bits */ + bool txbusy; /* A byte was written and TXPND is pending */ +#ifdef CONFIG_AB32VG1_UART0_ROMKEY + uint8_t keymatch; /* Number of key bytes matched so far */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int ab32vg1_setup(struct uart_dev_s *dev); +static void ab32vg1_shutdown(struct uart_dev_s *dev); +static int ab32vg1_attach(struct uart_dev_s *dev); +static void ab32vg1_detach(struct uart_dev_s *dev); +static int ab32vg1_interrupt(int irq, void *context, void *arg); +static int ab32vg1_ioctl(struct file *filep, int cmd, unsigned long arg); +static int ab32vg1_receive(struct uart_dev_s *dev, unsigned int *status); +static void ab32vg1_rxint(struct uart_dev_s *dev, bool enable); +static bool ab32vg1_rxavailable(struct uart_dev_s *dev); +static void ab32vg1_send(struct uart_dev_s *dev, int ch); +static void ab32vg1_txint(struct uart_dev_s *dev, bool enable); +static bool ab32vg1_txready(struct uart_dev_s *dev); +static bool ab32vg1_txempty(struct uart_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct uart_ops_s g_uart_ops = +{ + .setup = ab32vg1_setup, + .shutdown = ab32vg1_shutdown, + .attach = ab32vg1_attach, + .detach = ab32vg1_detach, + .ioctl = ab32vg1_ioctl, + .receive = ab32vg1_receive, + .rxint = ab32vg1_rxint, + .rxavailable = ab32vg1_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = ab32vg1_send, + .txint = ab32vg1_txint, + .txready = ab32vg1_txready, + .txempty = ab32vg1_txempty, +}; + +#ifdef CONFIG_AB32VG1_UART0_ROMKEY +static const uint8_t g_romkey[ROMKEY_LEN] = +{ + 0xf5, 0xa0, 0xa5, 0x96, 0x87, 0x5a +}; +#endif + +static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE]; +static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE]; + +static struct ab32vg1_uart_s g_uart0priv = +{ + .base = AB32VG1_UART0_BASE, + .baud = CONFIG_UART0_BAUD, + .irq = AB32VG1_IRQ_UART, + .stop2 = CONFIG_UART0_2STOP != 0, +}; + +static uart_dev_t g_uart0port = +{ +#ifdef CONFIG_UART0_SERIAL_CONSOLE + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_UART0_RXBUFSIZE, + .buffer = g_uart0rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART0_TXBUFSIZE, + .buffer = g_uart0txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart0priv, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline uint32_t ab32vg1_serialin(struct ab32vg1_uart_s *priv, + int offset) +{ + return getreg32(priv->base + offset); +} + +static inline void ab32vg1_serialout(struct ab32vg1_uart_s *priv, + int offset, uint32_t value) +{ + putreg32(value, priv->base + offset); +} + +static inline void ab32vg1_modifycon(struct ab32vg1_uart_s *priv, + uint32_t clrbits, uint32_t setbits) +{ + irqstate_t flags = up_irq_save(); + + modifyreg32(priv->base + AB32VG1_UART_CON_OFFSET, clrbits, setbits); + up_irq_restore(flags); +} + +/**************************************************************************** + * Name: ab32vg1_setup + * + * Description: + * Configure the UART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +static int ab32vg1_setup(struct uart_dev_s *dev) +{ + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + +#ifndef CONFIG_SUPPRESS_UART_CONFIG + ab32vg1_uart0_configure(priv->baud, priv->stop2); + priv->txbusy = false; +#endif + + return OK; +} + +/**************************************************************************** + * Name: ab32vg1_shutdown + * + * Description: + * Disable the UART interrupts. This method is called when the serial + * port is closed. The console keeps working for polled output. + * + ****************************************************************************/ + +static void ab32vg1_shutdown(struct uart_dev_s *dev) +{ + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + + ab32vg1_modifycon(priv, UART_CON_RXIE | UART_CON_TXIE, 0); +} + +/**************************************************************************** + * Name: ab32vg1_attach + * + * Description: + * Configure the UART to operate in interrupt driven mode. This method is + * called when the serial port is opened. + * + ****************************************************************************/ + +static int ab32vg1_attach(struct uart_dev_s *dev) +{ + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + int ret; + + ret = irq_attach(priv->irq, ab32vg1_interrupt, dev); + if (ret == OK) + { + up_enable_irq(priv->irq); + } + + return ret; +} + +/**************************************************************************** + * Name: ab32vg1_detach + * + * Description: + * Detach UART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. + * + ****************************************************************************/ + +static void ab32vg1_detach(struct uart_dev_s *dev) +{ + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + + up_disable_irq(priv->irq); + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: ab32vg1_interrupt + * + * Description: + * UART interrupt handler. The PIC source is shared by UART0/1/2 and is + * level triggered on RXPND/TXPND of every UART with the interrupt + * enabled. + * + ****************************************************************************/ + +static int ab32vg1_interrupt(int irq, void *context, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + uint32_t con; + int passes; + + for (passes = 0; passes < 256; passes++) + { + con = ab32vg1_serialin(priv, AB32VG1_UART_CON_OFFSET); + + if ((con & (UART_CON_RXIE | UART_CON_RXPND)) == + (UART_CON_RXIE | UART_CON_RXPND)) + { + uart_recvchars(dev); + } + else if ((con & (UART_CON_TXIE | UART_CON_TXPND)) == + (UART_CON_TXIE | UART_CON_TXPND)) + { + /* uart_xmitchars() either writes a new byte, which clears + * TXPND, or disables the TX interrupt. + */ + + priv->txbusy = false; + uart_xmitchars(dev); + } + else + { + break; + } + } + + return OK; +} + +/**************************************************************************** + * Name: ab32vg1_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int ab32vg1_ioctl(struct file *filep, int cmd, unsigned long arg) +{ +#ifdef CONFIG_SERIAL_TERMIOS + struct inode *inode = filep->f_inode; + struct uart_dev_s *dev = inode->i_private; + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + struct termios *termiosp = (struct termios *)arg; + int ret = OK; + + switch (cmd) + { + case TCGETS: + if (termiosp == NULL) + { + return -EINVAL; + } + + termiosp->c_cflag = CS8 | (priv->stop2 ? CSTOPB : 0); + cfsetispeed(termiosp, priv->baud); + break; + + case TCSETS: + if (termiosp == NULL) + { + return -EINVAL; + } + + /* Only 8N1/8N2 framing is supported */ + + if ((termiosp->c_cflag & (CSIZE | PARENB)) != CS8) + { + return -EINVAL; + } + + priv->stop2 = (termiosp->c_cflag & CSTOPB) != 0; + priv->baud = cfgetispeed(termiosp); + ab32vg1_uart0_configure(priv->baud, priv->stop2); + ab32vg1_modifycon(priv, 0, UART_CON_RXIE); + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +#else + return -ENOTTY; +#endif +} + +/**************************************************************************** + * Name: ab32vg1_receive + * + * Description: + * Called (usually) from the interrupt level to receive one character from + * the UART. Error bits associated with the receipt are provided in the + * return 'status'. + * + ****************************************************************************/ + +static int ab32vg1_receive(struct uart_dev_s *dev, unsigned int *status) +{ + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + uint8_t ch; + + ch = ab32vg1_serialin(priv, AB32VG1_UART_DATA_OFFSET) & 0xff; + ab32vg1_serialout(priv, AB32VG1_UART_CPND_OFFSET, UART_CPND_CRXPND); + *status = 0; + +#ifdef CONFIG_AB32VG1_UART0_ROMKEY + if (ch == g_romkey[priv->keymatch]) + { + if (++priv->keymatch == ROMKEY_LEN) + { + up_systemreset(); + } + } + else + { + priv->keymatch = (ch == g_romkey[0]) ? 1 : 0; + } +#endif + + return ch; +} + +/**************************************************************************** + * Name: ab32vg1_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void ab32vg1_rxint(struct uart_dev_s *dev, bool enable) +{ + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + if (enable) + { + ab32vg1_modifycon(priv, 0, UART_CON_RXIE); + } + else +#endif + { + ab32vg1_modifycon(priv, UART_CON_RXIE, 0); + } +} + +/**************************************************************************** + * Name: ab32vg1_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +static bool ab32vg1_rxavailable(struct uart_dev_s *dev) +{ + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + + return (ab32vg1_serialin(priv, AB32VG1_UART_CON_OFFSET) & + UART_CON_RXPND) != 0; +} + +/**************************************************************************** + * Name: ab32vg1_send + * + * Description: + * This method will send one byte on the UART. Writing the data register + * clears TXPND. + * + ****************************************************************************/ + +static void ab32vg1_send(struct uart_dev_s *dev, int ch) +{ + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + + priv->txbusy = true; + ab32vg1_serialout(priv, AB32VG1_UART_DATA_OFFSET, (uint8_t)ch); +} + +/**************************************************************************** + * Name: ab32vg1_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void ab32vg1_txint(struct uart_dev_s *dev, bool enable) +{ + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + if (enable) + { +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + ab32vg1_modifycon(priv, 0, UART_CON_TXIE); + + /* If the transmitter is idle no TX interrupt will come: fake one by + * calling uart_xmitchars() with interrupts disabled. + */ + + if (!priv->txbusy) + { + uart_xmitchars(dev); + } +#endif + } + else + { + ab32vg1_modifycon(priv, UART_CON_TXIE, 0); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: ab32vg1_txready + * + * Description: + * Return true if a new byte can be written: no byte in flight, or the + * last one has been shifted out (TXPND). The UART has no FIFO. + * + ****************************************************************************/ + +static bool ab32vg1_txready(struct uart_dev_s *dev) +{ + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)dev->priv; + + return !priv->txbusy || + (ab32vg1_serialin(priv, AB32VG1_UART_CON_OFFSET) & + UART_CON_TXPND) != 0; +} + +/**************************************************************************** + * Name: ab32vg1_txempty + * + * Description: + * Return true if all bytes have been sent + * + ****************************************************************************/ + +static bool ab32vg1_txempty(struct uart_dev_s *dev) +{ + return ab32vg1_txready(dev); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef USE_EARLYSERIALINIT + +/**************************************************************************** + * Name: riscv_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during boot up. This must be called + * before riscv_serialinit. + * + ****************************************************************************/ + +void riscv_earlyserialinit(void) +{ +#ifdef HAVE_CONSOLE + ab32vg1_setup(&CONSOLE_DEV); +#endif +} +#endif + +/**************************************************************************** + * Name: riscv_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that riscv_earlyserialinit was called previously. + * + ****************************************************************************/ + +void riscv_serialinit(void) +{ +#ifdef HAVE_CONSOLE + uart_register("/dev/console", &CONSOLE_DEV); +#endif + + uart_register("/dev/ttyS0", &TTYS0_DEV); +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +void up_putc(int ch) +{ +#ifdef HAVE_CONSOLE + struct ab32vg1_uart_s *priv = (struct ab32vg1_uart_s *)CONSOLE_DEV.priv; + irqstate_t flags; + + /* Let a byte sent by the interrupt driven path finish first. If TX + * interrupts are enabled, the TXPND left by our byte resumes them. + */ + + flags = up_irq_save(); + if (priv->txbusy) + { + while ((ab32vg1_serialin(priv, AB32VG1_UART_CON_OFFSET) & + UART_CON_TXPND) == 0) + { + } + } + + riscv_lowputc(ch); + priv->txbusy = true; + up_irq_restore(flags); +#endif +} + +#else /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +void up_putc(int ch) +{ + irqstate_t flags = up_irq_save(); + + riscv_lowputc(ch); + up_irq_restore(flags); +} + +#endif /* USE_SERIALDRIVER */ diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_start.c b/arch/risc-v/src/ab32vg1/ab32vg1_start.c new file mode 100644 index 00000000000..e0cc25e8ba6 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_start.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_start.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> + +#include <nuttx/init.h> +#include <arch/board/board.h> + +#include "riscv_internal.h" +#include "chip.h" +#include "ab32vg1.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +# define showprogress(c) riscv_lowputc(c) +#else +# define showprogress(c) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: __ab32vg1_start + * + * Description: + * C entry point, called from __start with the idle stack in place. The + * whole image (code and initialized data) has already been placed in RAM + * by the loader, so only .bss needs clearing. + * + ****************************************************************************/ + +void __ab32vg1_start(void) +{ + uint32_t *dest; + + /* The watchdog may have been left running by the boot code */ + + putreg32(WDTCON_DISABLE, AB32VG1_WDTCON); + + /* Clear .bss. We'll do this inline (vs. calling memset) just to be + * certain that there are no issues with the state of global variables. + */ + + for (dest = (uint32_t *)_sbss; dest < (uint32_t *)_ebss; ) + { + *dest++ = 0; + } + + /* Setup the system clock */ + + ab32vg1_clockconfig(); + + /* Configure the UART so we can get debug output */ + + ab32vg1_lowsetup(); + + showprogress('A'); + +#ifdef USE_EARLYSERIALINIT + riscv_earlyserialinit(); +#endif + + showprogress('B'); + + /* Do board initialization */ + + ab32vg1_boardinitialize(); + + showprogress('C'); + + /* Call nx_start() */ + + nx_start(); + + /* Shouldn't get here */ + + for (; ; ); +} diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_systemreset.c b/arch/risc-v/src/ab32vg1/ab32vg1_systemreset.c new file mode 100644 index 00000000000..df4f1ea679f --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_systemreset.c @@ -0,0 +1,54 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_systemreset.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/arch.h> + +#include "riscv_internal.h" +#include "chip.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_systemreset + * + * Description: + * Reset the chip with a 1 ms watchdog timeout. After the reset the mask + * ROM listens for its UART loader for a short time before booting from + * flash, so this is also how the host gets back to the ROM loader. + * + ****************************************************************************/ + +void up_systemreset(void) +{ + up_irq_save(); + putreg32(WDTCON_RESET_1MS, AB32VG1_WDTCON); + + for (; ; ); +} diff --git a/arch/risc-v/src/ab32vg1/ab32vg1_timerisr.c b/arch/risc-v/src/ab32vg1/ab32vg1_timerisr.c new file mode 100644 index 00000000000..232071cc629 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/ab32vg1_timerisr.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/ab32vg1_timerisr.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <time.h> + +#include <nuttx/arch.h> +#include <nuttx/clock.h> +#include <arch/board/board.h> + +#include "riscv_internal.h" +#include "chip.h" +#include "ab32vg1.h" +#include "hardware/ab32vg1_timer.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* TMR0 counts system clock cycles and wraps at TMR0PR */ + +#define TICK_RELOAD (AB32VG1_SYSCLK_FREQUENCY / CLK_TCK) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ab32vg1_timerisr + ****************************************************************************/ + +static int ab32vg1_timerisr(int irq, void *context, void *arg) +{ + putreg32(TMR_CPND_TPCLR, AB32VG1_TMR0CPND); + + /* Process timer interrupt */ + + nxsched_process_timer(); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize the timer + * interrupt. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + modifyreg32(AB32VG1_CLKGAT0, 0, CLKGAT0_TMR0); + + putreg32(0, AB32VG1_TMR0CON); + putreg32(0, AB32VG1_TMR0CNT); + putreg32(TICK_RELOAD - 1, AB32VG1_TMR0PR); + putreg32(TMR_CPND_TPCLR, AB32VG1_TMR0CPND); + + irq_attach(AB32VG1_IRQ_TMR0, ab32vg1_timerisr, NULL); + + putreg32(TMR_CON_INCSEL_SYSCLK | TMR_CON_TIE | TMR_CON_TMREN, + AB32VG1_TMR0CON); + + up_enable_irq(AB32VG1_IRQ_TMR0); +} diff --git a/arch/risc-v/src/ab32vg1/chip.h b/arch/risc-v/src/ab32vg1/chip.h new file mode 100644 index 00000000000..05fb3cc7653 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/chip.h @@ -0,0 +1,38 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/chip.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_AB32VG1_CHIP_H +#define __ARCH_RISCV_SRC_AB32VG1_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <arch/chip/chip.h> + +#include "hardware/ab32vg1_memorymap.h" +#include "hardware/ab32vg1_pic.h" +#include "hardware/ab32vg1_clk.h" + +#endif /* __ARCH_RISCV_SRC_AB32VG1_CHIP_H */ diff --git a/arch/risc-v/src/ab32vg1/hardware/ab32vg1_clk.h b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_clk.h new file mode 100644 index 00000000000..5fb3c85b097 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_clk.h @@ -0,0 +1,112 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/hardware/ab32vg1_clk.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_CLK_H +#define __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_CLK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "hardware/ab32vg1_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Clock, PLL and watchdog registers. The clock tree is not covered by the + * register manual; values follow the RT-Thread BSP (system_ab32vgx.c) and + * were checked on hardware by measuring TMR0 against the UART bit clock. + */ + +#define AB32VG1_CLKCON0 AB32VG1_SFR(0, 0x19) +#define AB32VG1_WDTCON AB32VG1_SFR(0, 0x1a) +#define AB32VG1_CLKCON1 AB32VG1_SFR(0, 0x1d) +#define AB32VG1_SPI0BAUD AB32VG1_SFR(0, 0x2c) +#define AB32VG1_PLL0DIV AB32VG1_SFR(3, 0x23) +#define AB32VG1_PLL0CON AB32VG1_SFR(3, 0x26) +#define AB32VG1_CLKCON2 AB32VG1_SFR(3, 0x2a) +#define AB32VG1_CLKGAT0 AB32VG1_SFR(3, 0x2c) +#define AB32VG1_CLKCON3 AB32VG1_SFR(3, 0x2f) +#define AB32VG1_CLKGAT1 AB32VG1_SFR(3, 0x3f) + +/* CLKCON0 */ + +#define CLKCON0_SYSCLK_RC2M (0 << 2) /* [3:2] system clock */ +#define CLKCON0_SYSCLK_SPLL (2 << 2) +#define CLKCON0_SYSCLK_MASK (3 << 2) +#define CLKCON0_SPLL_PLL0 (0 << 4) /* [6:4] SPLL source */ +#define CLKCON0_SPLL_XOSC26M (4 << 4) +#define CLKCON0_SPLL_MASK (7 << 4) + +/* CLKCON1 */ + +#define CLKCON1_UART_INC (1 << 14) /* uart_inc clock on */ + +/* CLKCON2 */ + +#define CLKCON2_SPLLDIV_SHIFT 8 /* [12:8] SPLL divider */ +#define CLKCON2_SPLLDIV_MASK (0x1f << CLKCON2_SPLLDIV_SHIFT) + +/* PLL0CON */ + +#define PLL0CON_VCO_SHIFT 3 /* [5:3] VCO band */ +#define PLL0CON_VCO_MASK (7 << PLL0CON_VCO_SHIFT) +#define PLL0CON_VCO_HIGH (1 << PLL0CON_VCO_SHIFT) /* > 206 MHz */ +#define PLL0CON_ANALOG_EN (1 << 6) +#define PLL0CON_LDO_EN (1 << 12) +#define PLL0CON_SDM_EN (1 << 18) +#define PLL0CON_DIV_UPDATE (1 << 20) + +/* PLL0 runs at 240 MHz from the 26 MHz crystal */ + +#define AB32VG1_XOSC_FREQUENCY 26000000 +#define AB32VG1_PLL0_FREQUENCY 240000000 +#define AB32VG1_PLL0DIV_240M (240 * 65536 / 26) + +/* CLKGAT0 / CLKGAT1 peripheral clock gates */ + +#define CLKGAT0_TMR0 (1 << 8) +#define CLKGAT0_SD0 (1 << 9) +#define CLKGAT0_UART0 (1 << 10) +#define CLKGAT0_HSUART (1 << 11) +#define CLKGAT0_SARADC (1 << 13) +#define CLKGAT0_USB (1 << 14) +#define CLKGAT0_PORT (1 << 17) +#define CLKGAT0_SPI0 (1 << 19) +#define CLKGAT0_UART1 (1 << 21) +#define CLKGAT0_TMR1 (1 << 24) +#define CLKGAT0_TMR2 (1 << 25) +#define CLKGAT1_TMR3 (1 << 8) +#define CLKGAT1_TMR4 (1 << 9) +#define CLKGAT1_TMR5 (1 << 10) +#define CLKGAT1_UART2 (1 << 11) +#define CLKGAT1_SPI1 (1 << 12) + +/* WDTCON (register manual, chapter 6). The *_WR fields are write keys. */ + +#define WDTCON_CLR 0x0000000a /* Kick the watchdog */ +#define WDTCON_DISABLE 0x00000aa0 /* WDTEN=0, RSTEN=0 */ +#define WDTCON_RESET_1MS 0x0a000110 /* 1 ms timeout, reset */ +#define WDTCON_WDTPND (1u << 31) + +#endif /* __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_CLK_H */ diff --git a/arch/risc-v/src/ab32vg1/hardware/ab32vg1_gpio.h b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_gpio.h new file mode 100644 index 00000000000..3119de9e0e8 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_gpio.h @@ -0,0 +1,81 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/hardware/ab32vg1_gpio.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_GPIO_H +#define __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "hardware/ab32vg1_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* GPIO ports A, B, E, F (register manual, chapter 1). Each port has the + * same register layout; ports are 16 registers apart. + */ + +#define AB32VG1_GPIOA_BASE AB32VG1_SFR(6, 0x00) +#define AB32VG1_GPIOB_BASE AB32VG1_SFR(6, 0x10) +#define AB32VG1_GPIOE_BASE AB32VG1_SFR(6, 0x20) +#define AB32VG1_GPIOF_BASE AB32VG1_SFR(6, 0x30) + +#define AB32VG1_GPIO_SET_OFFSET 0x00 /* Write 1: output high */ +#define AB32VG1_GPIO_CLR_OFFSET 0x04 /* Write 1: output low */ +#define AB32VG1_GPIO_DATA_OFFSET 0x08 /* Pin level / output latch */ +#define AB32VG1_GPIO_DIR_OFFSET 0x0c /* 1: input, 0: output */ +#define AB32VG1_GPIO_DE_OFFSET 0x10 /* 1: digital, 0: analog */ +#define AB32VG1_GPIO_FEN_OFFSET 0x14 /* 1: peripheral function */ +#define AB32VG1_GPIO_DRV_OFFSET 0x18 /* Drive strength */ +#define AB32VG1_GPIO_PU_OFFSET 0x1c /* 10K pull-up */ +#define AB32VG1_GPIO_PD_OFFSET 0x20 /* 10K pull-down */ +#define AB32VG1_GPIO_PU200K_OFFSET 0x24 +#define AB32VG1_GPIO_PD200K_OFFSET 0x28 +#define AB32VG1_GPIO_PU300_OFFSET 0x2c +#define AB32VG1_GPIO_PD300_OFFSET 0x30 + +/* Function mapping (register manual, FUNCMCON0..2). Writing 0xf to a + * 4-bit field clears it, writing another value selects a pin group; the + * other fields are not affected by writing 0. + */ + +#define AB32VG1_FUNCMCON0 AB32VG1_SFR(0, 0x07) +#define AB32VG1_FUNCMCON1 AB32VG1_SFR(0, 0x08) +#define AB32VG1_FUNCMCON2 AB32VG1_SFR(0, 0x09) + +#define FUNCMCON0_SD0MAP_SHIFT 0 +#define FUNCMCON0_SPI0MAP_SHIFT 4 +#define FUNCMCON0_UT0TXMAP_SHIFT 8 +#define FUNCMCON0_UT0RXMAP_SHIFT 12 +#define FUNCMCON0_HSUTTXMAP_SHIFT 16 +#define FUNCMCON0_HSUTRXMAP_SHIFT 20 +#define FUNCMCON0_UT1TXMAP_SHIFT 24 +#define FUNCMCON0_UT1RXMAP_SHIFT 28 + +#define FUNCMCON_CLEAR 0xf +#define FUNCMCON_G(n) (n) /* Map to pin group n */ +#define FUNCMCON_RX_ON_TX 0x7 /* UARTx RX on its TX pin */ + +#endif /* __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_GPIO_H */ diff --git a/arch/risc-v/src/ab32vg1/hardware/ab32vg1_memorymap.h b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_memorymap.h new file mode 100644 index 00000000000..cce8e2ab613 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_memorymap.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/hardware/ab32vg1_memorymap.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_MEMORYMAP_H +#define __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_MEMORYMAP_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* All peripheral registers live in the first 4 KB of the address space and + * are 32 bits wide. They are grouped in 16 "SFR banks" of 64 registers. + */ + +#define AB32VG1_SFR0_BASE 0x00000000 +#define AB32VG1_SFR1_BASE 0x00000100 +#define AB32VG1_SFR2_BASE 0x00000200 +#define AB32VG1_SFR3_BASE 0x00000300 +#define AB32VG1_SFR4_BASE 0x00000400 +#define AB32VG1_SFR5_BASE 0x00000500 +#define AB32VG1_SFR6_BASE 0x00000600 +#define AB32VG1_SFR7_BASE 0x00000700 +#define AB32VG1_SFR8_BASE 0x00000800 +#define AB32VG1_SFR9_BASE 0x00000900 + +#define AB32VG1_SFR(b, n) (AB32VG1_SFR##b##_BASE + ((n) << 2)) + +#endif /* __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_MEMORYMAP_H */ diff --git a/arch/risc-v/src/ab32vg1/hardware/ab32vg1_pic.h b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_pic.h new file mode 100644 index 00000000000..0c302437e88 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_pic.h @@ -0,0 +1,70 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/hardware/ab32vg1_pic.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_PIC_H +#define __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_PIC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "hardware/ab32vg1_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Interrupt controller and trap registers. These are not described in the + * register manual; the behaviour below was established by the probes in + * the port's bring-up journal and matches the RT-Thread BSP (ab32vg1.h). + */ + +#define AB32VG1_CPU_STATUS AB32VG1_SFR(5, 0x00) /* 0xc0000002 after an exception */ +#define AB32VG1_PICCONCLR AB32VG1_SFR(5, 0x0c) /* Write 1 to clear PICCON bits */ +#define AB32VG1_PICCONSET AB32VG1_SFR(5, 0x0d) /* Write 1 to set PICCON bits */ +#define AB32VG1_PICENCLR AB32VG1_SFR(5, 0x0e) +#define AB32VG1_PICENSET AB32VG1_SFR(5, 0x0f) +#define AB32VG1_PICCON AB32VG1_SFR(5, 0x10) /* Control */ +#define AB32VG1_PICEN AB32VG1_SFR(5, 0x11) /* Enable, 1 bit/source */ +#define AB32VG1_PICPR AB32VG1_SFR(5, 0x12) /* Priority: 1 = high */ +#define AB32VG1_PICADR AB32VG1_SFR(5, 0x13) /* Vector table base */ +#define AB32VG1_PICPND AB32VG1_SFR(5, 0x14) /* Pending */ +#define AB32VG1_EPICCON AB32VG1_SFR(5, 0x1e) /* PICCON.IE saved on trap */ +#define AB32VG1_EPC AB32VG1_SFR(5, 0x1f) /* Trap return address */ + +/* PICCON */ + +#define PICCON_IE (1 << 0) /* Low priority interrupt enable */ +#define PICCON_EN (1 << 1) /* Interrupt unit enable */ +#define PICCON_INIT 0x00010002 /* As set by the RT-Thread BSP */ + +/* Vector offsets from PICADR */ + +#define AB32VG1_VEC_EXCEPTION 0x10 /* Exceptions, high prio IRQs */ +#define AB32VG1_VEC_IRQ 0x40 /* Low priority IRQs */ +#define AB32VG1_VEC_CACHE 0x80 /* XIP cache miss */ + +/* Software interrupt: sets PICPND bit 2 */ + +#define AB32VG1_SWINT_INSN 0xb0030057 + +#endif /* __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_PIC_H */ diff --git a/arch/risc-v/src/ab32vg1/hardware/ab32vg1_timer.h b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_timer.h new file mode 100644 index 00000000000..bc442a90b76 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_timer.h @@ -0,0 +1,66 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/hardware/ab32vg1_timer.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_TIMER_H +#define __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_TIMER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "hardware/ab32vg1_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Timer 0/1/2 (register manual, chapter 2) */ + +#define AB32VG1_TMR0CON AB32VG1_SFR(0, 0x14) +#define AB32VG1_TMR0CPND AB32VG1_SFR(0, 0x15) +#define AB32VG1_TMR0CNT AB32VG1_SFR(0, 0x16) +#define AB32VG1_TMR0PR AB32VG1_SFR(0, 0x17) + +#define AB32VG1_TMR1CON AB32VG1_SFR(0, 0x35) +#define AB32VG1_TMR1CPND AB32VG1_SFR(0, 0x36) +#define AB32VG1_TMR1CNT AB32VG1_SFR(0, 0x37) +#define AB32VG1_TMR1PR AB32VG1_SFR(0, 0x38) + +#define AB32VG1_TMR2CON AB32VG1_SFR(0, 0x3a) +#define AB32VG1_TMR2CPND AB32VG1_SFR(0, 0x3b) +#define AB32VG1_TMR2CNT AB32VG1_SFR(0, 0x3c) +#define AB32VG1_TMR2PR AB32VG1_SFR(0, 0x3d) + +/* TMRxCON */ + +#define TMR_CON_TMREN (1 << 0) /* Timer enable */ +#define TMR_CON_INCSEL_SHIFT 2 /* Count source */ +#define TMR_CON_INCSEL_SYSCLK (0 << TMR_CON_INCSEL_SHIFT) +#define TMR_CON_INCSRC (1 << 6) /* 1: external pin */ +#define TMR_CON_TIE (1 << 7) /* Overflow int enable */ +#define TMR_CON_TPND (1 << 9) /* Overflow pending */ + +/* TMRxCPND */ + +#define TMR_CPND_TPCLR (1 << 9) + +#endif /* __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_TIMER_H */ diff --git a/arch/risc-v/src/ab32vg1/hardware/ab32vg1_uart.h b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_uart.h new file mode 100644 index 00000000000..e9f334b3470 --- /dev/null +++ b/arch/risc-v/src/ab32vg1/hardware/ab32vg1_uart.h @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/risc-v/src/ab32vg1/hardware/ab32vg1_uart.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_UART_H +#define __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_UART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "hardware/ab32vg1_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* UART0/1/2 (register manual, chapter 8). Each UART has the same four + * consecutive registers. + */ + +#define AB32VG1_UART0_BASE AB32VG1_SFR(0, 0x10) +#define AB32VG1_UART1_BASE AB32VG1_SFR(0, 0x30) +#define AB32VG1_UART2_BASE AB32VG1_SFR(9, 0x18) + +#define AB32VG1_UART_CON_OFFSET 0x00 +#define AB32VG1_UART_CPND_OFFSET 0x04 +#define AB32VG1_UART_BAUD_OFFSET 0x08 +#define AB32VG1_UART_DATA_OFFSET 0x0c + +/* UARTxCON */ + +#define UART_CON_UTEN (1 << 0) /* UART enable */ +#define UART_CON_BIT9EN (1 << 1) /* 9-bit mode */ +#define UART_CON_RXIE (1 << 2) /* RX interrupt enable */ +#define UART_CON_TXIE (1 << 3) /* TX interrupt enable */ +#define UART_CON_SB2EN (1 << 4) /* 2 stop bits */ +#define UART_CON_CLKSRC (1 << 5) /* 0: system clock, 1: uart_inc */ +#define UART_CON_ONELINE (1 << 6) /* TX/RX on one pin */ +#define UART_CON_RXEN (1 << 7) /* RX enable */ +#define UART_CON_TXPND (1 << 8) /* TX of one byte finished */ +#define UART_CON_RXPND (1 << 9) /* RX of one byte finished */ + +/* UARTxCPND */ + +#define UART_CPND_CTXPND (1 << 8) +#define UART_CPND_CRXPND (1 << 9) +#define UART_CPND_CKEYPND (1 << 16) +#define UART_CPND_CRSTKEYPND (1 << 17) + +/* UARTxBAUD: baud = Fclk / (n + 1); RX in [31:16], TX in [15:0]. With + * CLKSRC = 1 the clock is uart_inc = XOSC 26 MHz / 2. + */ + +#define UART_INC_FREQUENCY 13000000 +#define UART_BAUD(n) (((uint32_t)(n) << 16) | (uint32_t)(n)) + +#endif /* __ARCH_RISCV_SRC_AB32VG1_HARDWARE_AB32VG1_UART_H */ diff --git a/arch/risc-v/src/common/CMakeLists.txt b/arch/risc-v/src/common/CMakeLists.txt index e2b8f8bb902..7b09b378c51 100644 --- a/arch/risc-v/src/common/CMakeLists.txt +++ b/arch/risc-v/src/common/CMakeLists.txt @@ -22,12 +22,14 @@ set(SRCS) -list(APPEND SRCS riscv_exception_common.S riscv_vectors.S) -list(APPEND SRCS riscv_saveusercontext.S) +if(NOT CONFIG_ARCH_RV_CUSTOM_TRAP) + list(APPEND SRCS riscv_exception_common.S riscv_vectors.S) + list(APPEND SRCS riscv_saveusercontext.S riscv_getnewintctx.c) +endif() list(APPEND SRCS riscv_allocateheap.c riscv_cpuidlestack.c) list(APPEND SRCS riscv_cpuinfo.c riscv_createstack.c riscv_doirq.c riscv_exception.c) -list(APPEND SRCS riscv_exit.c riscv_getintstack.c riscv_getnewintctx.c) +list(APPEND SRCS riscv_exit.c riscv_getintstack.c) list(APPEND SRCS riscv_initialize.c riscv_initialstate.c riscv_modifyreg32.c) list(APPEND SRCS riscv_nputs.c riscv_registerdump.c) list(APPEND SRCS riscv_releasestack.c) diff --git a/arch/risc-v/src/common/Make.defs b/arch/risc-v/src/common/Make.defs index 4b46fc9ccad..1899442bfa3 100644 --- a/arch/risc-v/src/common/Make.defs +++ b/arch/risc-v/src/common/Make.defs @@ -22,19 +22,27 @@ STARTUP_OBJS = crt0$(OBJEXT) -# Specify our general Assembly files +# Specify our general Assembly files. Chips without the standard trap +# architecture provide their own trap entry and context helpers. + +ifneq ($(CONFIG_ARCH_RV_CUSTOM_TRAP),y) CMN_ASRCS += riscv_vectors.S riscv_exception_common.S CMN_ASRCS += riscv_saveusercontext.S +endif # Specify C code within the common directory to be included CMN_CSRCS += riscv_initialize.c riscv_swint.c CMN_CSRCS += riscv_allocateheap.c riscv_createstack.c riscv_cpuinfo.c CMN_CSRCS += riscv_cpuidlestack.c riscv_doirq.c riscv_exit.c riscv_exception.c -CMN_CSRCS += riscv_getnewintctx.c riscv_getintstack.c riscv_initialstate.c +CMN_CSRCS += riscv_getintstack.c riscv_initialstate.c CMN_CSRCS += riscv_modifyreg32.c riscv_nputs.c riscv_releasestack.c CMN_CSRCS += riscv_registerdump.c riscv_stackframe.c riscv_switchcontext.c CMN_CSRCS += riscv_usestack.c riscv_tcbinfo.c +ifneq ($(CONFIG_ARCH_RV_CUSTOM_TRAP),y) +CMN_CSRCS += riscv_getnewintctx.c +endif + ifeq ($(CONFIG_ENABLE_ALL_SIGNALS),y) CMN_CSRCS += riscv_schedulesigaction.c riscv_sigdeliver.c endif
