From e0464694216ac2007ac672c43a17ea78eece82a6 Mon Sep 17 00:00:00 2001 From: Yaochenger <1516081466@qq.com> Date: Wed, 14 May 2025 10:30:41 +0800 Subject: [PATCH 1/3] [add] add xuantie e906 series --- bsp/xuantie/libraries/SConscript | 15 + .../libraries/device_drivers/SConscript | 16 + .../libraries/device_drivers/drv_usart.c | 219 + .../libraries/device_drivers/drv_usart.h | 38 + .../libraries/xuantie_libraries/SConscript | 15 + .../chip_riscv_dummy/SConscript | 15 + .../chip_riscv_dummy/gcc_flash_smartl.ld | 259 + .../chip_riscv_dummy/gcc_flash_xiaohui.ld | 268 + .../gcc_flash_xiaohui.ld.sram | 264 + .../chip_riscv_dummy/include/SConscript | 13 + .../include/asm/riscv_asm_macro.h | 598 +++ .../chip_riscv_dummy/include/asm/riscv_csr.h | 177 + .../chip_riscv_dummy/include/csi_config.h | 0 .../chip_riscv_dummy/include/drv/dev_tag.h | 102 + .../chip_riscv_dummy/include/dw_timer_ll.h | 167 + .../chip_riscv_dummy/include/dw_uart.h | 0 .../chip_riscv_dummy/include/dw_uart_ll.h | 429 ++ .../chip_riscv_dummy/include/soc.h | 322 ++ .../chip_riscv_dummy/include/sys_clk.h | 117 + .../chip_riscv_dummy/src/SConscript | 15 + .../chip_riscv_dummy/src/arch/SConscript | 16 + .../chip_riscv_dummy/src/arch/c906/startup.S | 128 + .../chip_riscv_dummy/src/arch/c906/system.c | 274 ++ .../chip_riscv_dummy/src/arch/c906/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/c906/vectors.S | 412 ++ .../src/arch/c906fd/startup.S | 128 + .../chip_riscv_dummy/src/arch/c906fd/system.c | 274 ++ .../chip_riscv_dummy/src/arch/c906fd/trap_c.c | 64 + .../src/arch/c906fd/vectors.S | 412 ++ .../src/arch/c906fdv/startup.S | 128 + .../src/arch/c906fdv/system.c | 274 ++ .../src/arch/c906fdv/trap_c.c | 64 + .../src/arch/c906fdv/vectors.S | 412 ++ .../src/arch/c907-rv32/startup.S | 188 + .../src/arch/c907-rv32/system.c | 326 ++ .../src/arch/c907-rv32/trap_c.c | 64 + .../src/arch/c907-rv32/vectors.S | 842 ++++ .../chip_riscv_dummy/src/arch/c907/startup.S | 188 + .../chip_riscv_dummy/src/arch/c907/system.c | 326 ++ .../chip_riscv_dummy/src/arch/c907/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/c907/vectors.S | 842 ++++ .../src/arch/c907fd-rv32/startup.S | 188 + .../src/arch/c907fd-rv32/system.c | 326 ++ .../src/arch/c907fd-rv32/trap_c.c | 64 + .../src/arch/c907fd-rv32/vectors.S | 842 ++++ .../src/arch/c907fd/startup.S | 188 + .../chip_riscv_dummy/src/arch/c907fd/system.c | 326 ++ .../chip_riscv_dummy/src/arch/c907fd/trap_c.c | 64 + .../src/arch/c907fd/vectors.S | 842 ++++ .../src/arch/c907fdv-rv32/startup.S | 188 + .../src/arch/c907fdv-rv32/system.c | 326 ++ .../src/arch/c907fdv-rv32/trap_c.c | 64 + .../src/arch/c907fdv-rv32/vectors.S | 842 ++++ .../src/arch/c907fdv/startup.S | 188 + .../src/arch/c907fdv/system.c | 326 ++ .../src/arch/c907fdv/trap_c.c | 64 + .../src/arch/c907fdv/vectors.S | 842 ++++ .../src/arch/c907fdvm-rv32/startup.S | 188 + .../src/arch/c907fdvm-rv32/system.c | 326 ++ .../src/arch/c907fdvm-rv32/trap_c.c | 64 + .../src/arch/c907fdvm-rv32/vectors.S | 842 ++++ .../src/arch/c907fdvm/startup.S | 188 + .../src/arch/c907fdvm/system.c | 326 ++ .../src/arch/c907fdvm/trap_c.c | 64 + .../src/arch/c907fdvm/vectors.S | 842 ++++ .../chip_riscv_dummy/src/arch/c908/startup.S | 188 + .../chip_riscv_dummy/src/arch/c908/system.c | 316 ++ .../chip_riscv_dummy/src/arch/c908/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/c908/vectors.S | 527 ++ .../chip_riscv_dummy/src/arch/c908i/startup.S | 188 + .../chip_riscv_dummy/src/arch/c908i/system.c | 316 ++ .../chip_riscv_dummy/src/arch/c908i/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/c908i/vectors.S | 527 ++ .../chip_riscv_dummy/src/arch/c908v/startup.S | 188 + .../chip_riscv_dummy/src/arch/c908v/system.c | 316 ++ .../chip_riscv_dummy/src/arch/c908v/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/c908v/vectors.S | 527 ++ .../src/arch/c910v2/startup.S | 188 + .../chip_riscv_dummy/src/arch/c910v2/system.c | 316 ++ .../chip_riscv_dummy/src/arch/c910v2/trap_c.c | 64 + .../src/arch/c910v2/vectors.S | 521 ++ .../src/arch/c910v3-cp/startup.S | 188 + .../src/arch/c910v3-cp/system.c | 324 ++ .../src/arch/c910v3-cp/trap_c.c | 64 + .../src/arch/c910v3-cp/vectors.S | 521 ++ .../src/arch/c910v3/startup.S | 188 + .../chip_riscv_dummy/src/arch/c910v3/system.c | 324 ++ .../chip_riscv_dummy/src/arch/c910v3/trap_c.c | 64 + .../src/arch/c910v3/vectors.S | 521 ++ .../src/arch/c920v2/startup.S | 188 + .../chip_riscv_dummy/src/arch/c920v2/system.c | 316 ++ .../chip_riscv_dummy/src/arch/c920v2/trap_c.c | 64 + .../src/arch/c920v2/vectors.S | 521 ++ .../src/arch/c920v3-cp/startup.S | 188 + .../src/arch/c920v3-cp/system.c | 324 ++ .../src/arch/c920v3-cp/trap_c.c | 64 + .../src/arch/c920v3-cp/vectors.S | 521 ++ .../src/arch/c920v3/startup.S | 188 + .../chip_riscv_dummy/src/arch/c920v3/system.c | 324 ++ .../chip_riscv_dummy/src/arch/c920v3/trap_c.c | 64 + .../src/arch/c920v3/vectors.S | 521 ++ .../chip_riscv_dummy/src/arch/e902/SConscript | 13 + .../chip_riscv_dummy/src/arch/e902/startup.S | 135 + .../chip_riscv_dummy/src/arch/e902/system.c | 100 + .../chip_riscv_dummy/src/arch/e902/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/e902/vectors.S | 383 ++ .../chip_riscv_dummy/src/arch/e902m/startup.S | 134 + .../chip_riscv_dummy/src/arch/e902m/system.c | 100 + .../chip_riscv_dummy/src/arch/e902m/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/e902m/vectors.S | 383 ++ .../src/arch/e902mt/startup.S | 134 + .../chip_riscv_dummy/src/arch/e902mt/system.c | 100 + .../chip_riscv_dummy/src/arch/e902mt/trap_c.c | 64 + .../src/arch/e902mt/vectors.S | 383 ++ .../chip_riscv_dummy/src/arch/e902t/startup.S | 134 + .../chip_riscv_dummy/src/arch/e902t/system.c | 100 + .../chip_riscv_dummy/src/arch/e902t/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/e902t/vectors.S | 383 ++ .../chip_riscv_dummy/src/arch/e906/SConscript | 13 + .../chip_riscv_dummy/src/arch/e906/startup.S | 170 + .../chip_riscv_dummy/src/arch/e906/system.c | 113 + .../chip_riscv_dummy/src/arch/e906/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/e906/vectors.S | 591 +++ .../chip_riscv_dummy/src/arch/e906f/startup.S | 168 + .../chip_riscv_dummy/src/arch/e906f/system.c | 113 + .../chip_riscv_dummy/src/arch/e906f/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/e906f/vectors.S | 591 +++ .../src/arch/e906fd/SConscript | 13 + .../src/arch/e906fd/startup.S | 169 + .../chip_riscv_dummy/src/arch/e906fd/system.c | 113 + .../chip_riscv_dummy/src/arch/e906fd/trap_c.c | 64 + .../src/arch/e906fd/vectors.S | 591 +++ .../src/arch/e906fdp/startup.S | 168 + .../src/arch/e906fdp/system.c | 113 + .../src/arch/e906fdp/trap_c.c | 64 + .../src/arch/e906fdp/vectors.S | 591 +++ .../src/arch/e906fp/startup.S | 168 + .../chip_riscv_dummy/src/arch/e906fp/system.c | 113 + .../chip_riscv_dummy/src/arch/e906fp/trap_c.c | 64 + .../src/arch/e906fp/vectors.S | 591 +++ .../chip_riscv_dummy/src/arch/e906p/startup.S | 168 + .../chip_riscv_dummy/src/arch/e906p/system.c | 113 + .../chip_riscv_dummy/src/arch/e906p/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/e906p/vectors.S | 591 +++ .../chip_riscv_dummy/src/arch/e907/SConscript | 13 + .../chip_riscv_dummy/src/arch/e907/startup.S | 173 + .../chip_riscv_dummy/src/arch/e907/system.c | 113 + .../chip_riscv_dummy/src/arch/e907/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/e907/vectors.S | 588 +++ .../chip_riscv_dummy/src/arch/e907f/startup.S | 172 + .../chip_riscv_dummy/src/arch/e907f/system.c | 113 + .../chip_riscv_dummy/src/arch/e907f/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/e907f/vectors.S | 588 +++ .../src/arch/e907fd/startup.S | 172 + .../chip_riscv_dummy/src/arch/e907fd/system.c | 113 + .../chip_riscv_dummy/src/arch/e907fd/trap_c.c | 64 + .../src/arch/e907fd/vectors.S | 588 +++ .../src/arch/e907fdp/startup.S | 172 + .../src/arch/e907fdp/system.c | 113 + .../src/arch/e907fdp/trap_c.c | 64 + .../src/arch/e907fdp/vectors.S | 588 +++ .../src/arch/e907fp/startup.S | 172 + .../chip_riscv_dummy/src/arch/e907fp/system.c | 113 + .../chip_riscv_dummy/src/arch/e907fp/trap_c.c | 64 + .../src/arch/e907fp/vectors.S | 588 +++ .../chip_riscv_dummy/src/arch/e907p/startup.S | 172 + .../chip_riscv_dummy/src/arch/e907p/system.c | 113 + .../chip_riscv_dummy/src/arch/e907p/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/e907p/vectors.S | 588 +++ .../src/arch/r908-cp/startup.S | 292 ++ .../src/arch/r908-cp/system.c | 406 ++ .../src/arch/r908-cp/trap_c.c | 64 + .../src/arch/r908-cp/vectors.S | 983 ++++ .../chip_riscv_dummy/src/arch/r908/startup.S | 292 ++ .../chip_riscv_dummy/src/arch/r908/system.c | 406 ++ .../chip_riscv_dummy/src/arch/r908/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/r908/vectors.S | 983 ++++ .../src/arch/r908fd-cp/startup.S | 292 ++ .../src/arch/r908fd-cp/system.c | 406 ++ .../src/arch/r908fd-cp/trap_c.c | 64 + .../src/arch/r908fd-cp/vectors.S | 983 ++++ .../src/arch/r908fd/startup.S | 292 ++ .../chip_riscv_dummy/src/arch/r908fd/system.c | 406 ++ .../chip_riscv_dummy/src/arch/r908fd/trap_c.c | 64 + .../src/arch/r908fd/vectors.S | 983 ++++ .../src/arch/r908fdv-cp/startup.S | 292 ++ .../src/arch/r908fdv-cp/system.c | 406 ++ .../src/arch/r908fdv-cp/trap_c.c | 64 + .../src/arch/r908fdv-cp/vectors.S | 983 ++++ .../src/arch/r908fdv/startup.S | 292 ++ .../src/arch/r908fdv/system.c | 406 ++ .../src/arch/r908fdv/trap_c.c | 64 + .../src/arch/r908fdv/vectors.S | 983 ++++ .../chip_riscv_dummy/src/arch/r910/startup.S | 188 + .../chip_riscv_dummy/src/arch/r910/system.c | 316 ++ .../chip_riscv_dummy/src/arch/r910/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/r910/vectors.S | 526 ++ .../chip_riscv_dummy/src/arch/r920/startup.S | 188 + .../chip_riscv_dummy/src/arch/r920/system.c | 316 ++ .../chip_riscv_dummy/src/arch/r920/trap_c.c | 64 + .../chip_riscv_dummy/src/arch/r920/vectors.S | 526 ++ .../chip_riscv_dummy/src/drivers/SConscript | 11 + .../chip_riscv_dummy/src/drivers/adc.c | 450 ++ .../chip_riscv_dummy/src/drivers/aes.c | 349 ++ .../chip_riscv_dummy/src/drivers/clk.c | 62 + .../chip_riscv_dummy/src/drivers/codec.c | 784 +++ .../chip_riscv_dummy/src/drivers/crc.c | 455 ++ .../chip_riscv_dummy/src/drivers/dma.c | 383 ++ .../chip_riscv_dummy/src/drivers/dw_uart_ll.c | 164 + .../chip_riscv_dummy/src/drivers/etb.c | 178 + .../chip_riscv_dummy/src/drivers/gpio.c | 271 ++ .../chip_riscv_dummy/src/drivers/gpio_pin.c | 215 + .../chip_riscv_dummy/src/drivers/i2s.c | 888 ++++ .../chip_riscv_dummy/src/drivers/iic.c | 1180 +++++ .../chip_riscv_dummy/src/drivers/mbox.c | 213 + .../chip_riscv_dummy/src/drivers/pinmux.c | 78 + .../src/drivers/power_manage.c | 292 ++ .../chip_riscv_dummy/src/drivers/pwm.c | 272 ++ .../chip_riscv_dummy/src/drivers/qspi.c | 419 ++ .../chip_riscv_dummy/src/drivers/rsa.c | 1458 ++++++ .../chip_riscv_dummy/src/drivers/rtc.c | 291 ++ .../chip_riscv_dummy/src/drivers/sha.c | 490 ++ .../chip_riscv_dummy/src/drivers/spi.c | 754 +++ .../chip_riscv_dummy/src/drivers/spiflash.c | 789 +++ .../chip_riscv_dummy/src/drivers/timer.c | 224 + .../chip_riscv_dummy/src/drivers/trng.c | 75 + .../chip_riscv_dummy/src/drivers/uart.c | 809 +++ .../chip_riscv_dummy/src/drivers/wdt.c | 227 + .../chip_riscv_dummy/src/sys/SConscript | 15 + .../chip_riscv_dummy/src/sys/devices.c | 69 + .../chip_riscv_dummy/src/sys/irq.c | 240 + .../chip_riscv_dummy/src/sys/irq_port.c | 98 + .../chip_riscv_dummy/src/sys/sys_clk.c | 96 + .../chip_riscv_dummy/src/sys/target_get.c | 190 + .../chip_riscv_dummy/src/sys/tick.c | 193 + .../libraries/xuantie_libraries/csi/README.md | 21 + .../xuantie_libraries/csi/SConscript | 15 + .../xuantie_libraries/csi/csi2/SConscript | 15 + .../csi/csi2/include/core/README.txt | 1 + .../csi/csi2/include/core/core_rv32.h | 1451 ++++++ .../csi/csi2/include/core/core_rv64.h | 2003 ++++++++ .../csi/csi2/include/core/csi_arm64_gcc.h | 3286 +++++++++++++ .../csi/csi2/include/core/csi_gcc.h | 3293 +++++++++++++ .../csi/csi2/include/core/csi_rv32_gcc.h | 2935 +++++++++++ .../csi/csi2/include/core/csi_rv64_gcc.h | 4329 +++++++++++++++++ .../csi/csi2/include/core/csi_rv_common.h | 129 + .../csi/csi2/include/csi_core.h | 186 + .../csi/csi2/include/drv/adc.h | 212 + .../csi/csi2/include/drv/aes.h | 309 ++ .../csi/csi2/include/drv/baud_calc.h | 58 + .../csi/csi2/include/drv/clk.h | 50 + .../csi/csi2/include/drv/codec.h | 450 ++ .../csi/csi2/include/drv/common.h | 151 + .../csi/csi2/include/drv/crc.h | 136 + .../csi/csi2/include/drv/des.h | 174 + .../csi/csi2/include/drv/dma.h | 216 + .../csi/csi2/include/drv/drv_fft.h | 83 + .../csi/csi2/include/drv/ecdh.h | 92 + .../csi/csi2/include/drv/ecdsa.h | 112 + .../csi/csi2/include/drv/eflash.h | 140 + .../csi/csi2/include/drv/efuse.h | 93 + .../csi/csi2/include/drv/etb.h | 102 + .../csi/csi2/include/drv/eth.h | 111 + .../csi/csi2/include/drv/eth_mac.h | 377 ++ .../csi/csi2/include/drv/eth_phy.h | 124 + .../csi/csi2/include/drv/fft.h | 87 + .../csi/csi2/include/drv/gpio.h | 214 + .../csi/csi2/include/drv/gpio_pin.h | 143 + .../csi/csi2/include/drv/hmac.h | 122 + .../csi/csi2/include/drv/i2s.h | 397 ++ .../csi/csi2/include/drv/iic.h | 338 ++ .../csi/csi2/include/drv/intc.h | 178 + .../csi/csi2/include/drv/io.h | 131 + .../csi/csi2/include/drv/irq.h | 149 + .../csi/csi2/include/drv/iso7816.h | 409 ++ .../csi/csi2/include/drv/list.h | 350 ++ .../csi/csi2/include/drv/mbox.h | 104 + .../csi/csi2/include/drv/pin.h | 197 + .../csi/csi2/include/drv/pm.h | 122 + .../csi/csi2/include/drv/pmu.h | 118 + .../csi/csi2/include/drv/porting.h | 184 + .../csi/csi2/include/drv/pwm.h | 172 + .../csi/csi2/include/drv/qspi.h | 304 ++ .../csi/csi2/include/drv/ringbuf.h | 62 + .../csi/csi2/include/drv/rng.h | 54 + .../csi/csi2/include/drv/rsa.h | 198 + .../csi/csi2/include/drv/rtc.h | 148 + .../csi/csi2/include/drv/sasc.h | 144 + .../csi/csi2/include/drv/sdif.h | 441 ++ .../csi/csi2/include/drv/sensor.h | 193 + .../csi/csi2/include/drv/sha.h | 128 + .../csi/csi2/include/drv/spi.h | 293 ++ .../csi/csi2/include/drv/spiflash.h | 303 ++ .../csi/csi2/include/drv/spinand.h | 321 ++ .../csi/csi2/include/drv/tee.h | 643 +++ .../csi/csi2/include/drv/tick.h | 79 + .../csi/csi2/include/drv/timer.h | 132 + .../csi/csi2/include/drv/tipc.h | 56 + .../csi/csi2/include/drv/uart.h | 241 + .../csi/csi2/include/drv/usi.h | 42 + .../csi/csi2/include/drv/usi_iic.h | 260 + .../csi/csi2/include/drv/usi_spi.h | 229 + .../csi/csi2/include/drv/usi_usart.h | 192 + .../csi/csi2/include/drv/wdt.h | 139 + .../csi/csi2/include/syslog.h | 121 + .../xuantie_libraries/pre_main/SConscript | 11 + .../xuantie_libraries/pre_main/pre_main.c | 82 + .../xuantie_libraries/pre_main/pre_main.h | 12 + .../xuantie_libraries/pre_main/sub_libcpu.S | 15 + bsp/xuantie/smartl/e906/.config | 1355 ++++++ bsp/xuantie/smartl/e906/Kconfig | 18 + bsp/xuantie/smartl/e906/README.md | 107 + bsp/xuantie/smartl/e906/SConscript | 15 + bsp/xuantie/smartl/e906/SConstruct | 61 + .../smartl/e906/applications/SConscript | 10 + bsp/xuantie/smartl/e906/applications/main.c | 18 + bsp/xuantie/smartl/e906/board/Kconfig | 43 + bsp/xuantie/smartl/e906/board/SConscript | 15 + bsp/xuantie/smartl/e906/board/board.c | 41 + bsp/xuantie/smartl/e906/board/board.h | 442 ++ bsp/xuantie/smartl/e906/figures/1.env.png | Bin 0 -> 27810 bytes bsp/xuantie/smartl/e906/figures/2.scons.png | Bin 0 -> 50557 bytes bsp/xuantie/smartl/e906/figures/3.vscode.png | Bin 0 -> 168160 bytes bsp/xuantie/smartl/e906/figures/4.run1.png | Bin 0 -> 9213 bytes bsp/xuantie/smartl/e906/figures/5.run2.png | Bin 0 -> 15704 bytes bsp/xuantie/smartl/e906/figures/6.cmd1.png | Bin 0 -> 23262 bytes bsp/xuantie/smartl/e906/figures/7.cmd2.png | Bin 0 -> 145863 bytes bsp/xuantie/smartl/e906/figures/8.cmd3.png | Bin 0 -> 241937 bytes bsp/xuantie/smartl/e906/objdump.bat | 8 + bsp/xuantie/smartl/e906/qemu.bat | 91 + bsp/xuantie/smartl/e906/rtconfig.h | 396 ++ bsp/xuantie/smartl/e906/rtconfig.py | 91 + 332 files changed, 97892 insertions(+) create mode 100644 bsp/xuantie/libraries/SConscript create mode 100644 bsp/xuantie/libraries/device_drivers/SConscript create mode 100644 bsp/xuantie/libraries/device_drivers/drv_usart.c create mode 100644 bsp/xuantie/libraries/device_drivers/drv_usart.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_smartl.ld create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_xiaohui.ld create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_xiaohui.ld.sram create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/asm/riscv_asm_macro.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/asm/riscv_csr.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/csi_config.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/drv/dev_tag.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/dw_timer_ll.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/dw_uart.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/dw_uart_ll.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/soc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/sys_clk.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/startup.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/system.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/trap_c.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/vectors.S create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/adc.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/aes.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/clk.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/codec.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/crc.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/dma.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/dw_uart_ll.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/etb.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/gpio.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/gpio_pin.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/i2s.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/iic.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/mbox.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/pinmux.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/power_manage.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/pwm.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/qspi.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/rsa.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/rtc.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/sha.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/spi.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/spiflash.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/timer.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/trng.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/uart.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/wdt.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/devices.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/irq.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/irq_port.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/sys_clk.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/target_get.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/tick.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/README.md create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/README.txt create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/core_rv32.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/core_rv64.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_arm64_gcc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_gcc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv32_gcc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv64_gcc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv_common.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/csi_core.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/adc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/aes.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/baud_calc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/clk.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/codec.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/common.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/crc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/des.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/dma.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/drv_fft.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ecdh.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ecdsa.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eflash.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/efuse.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/etb.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth_mac.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth_phy.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/fft.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/gpio.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/gpio_pin.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/hmac.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/i2s.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/iic.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/intc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/io.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/irq.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/iso7816.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/list.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/mbox.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pin.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pm.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pmu.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/porting.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pwm.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/qspi.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ringbuf.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rng.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rsa.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rtc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sasc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sdif.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sensor.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sha.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spi.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spiflash.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spinand.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tee.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tick.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/timer.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tipc.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/uart.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_iic.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_spi.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_usart.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/wdt.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/syslog.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/pre_main/SConscript create mode 100644 bsp/xuantie/libraries/xuantie_libraries/pre_main/pre_main.c create mode 100644 bsp/xuantie/libraries/xuantie_libraries/pre_main/pre_main.h create mode 100644 bsp/xuantie/libraries/xuantie_libraries/pre_main/sub_libcpu.S create mode 100644 bsp/xuantie/smartl/e906/.config create mode 100644 bsp/xuantie/smartl/e906/Kconfig create mode 100644 bsp/xuantie/smartl/e906/README.md create mode 100644 bsp/xuantie/smartl/e906/SConscript create mode 100644 bsp/xuantie/smartl/e906/SConstruct create mode 100644 bsp/xuantie/smartl/e906/applications/SConscript create mode 100644 bsp/xuantie/smartl/e906/applications/main.c create mode 100644 bsp/xuantie/smartl/e906/board/Kconfig create mode 100644 bsp/xuantie/smartl/e906/board/SConscript create mode 100644 bsp/xuantie/smartl/e906/board/board.c create mode 100644 bsp/xuantie/smartl/e906/board/board.h create mode 100644 bsp/xuantie/smartl/e906/figures/1.env.png create mode 100644 bsp/xuantie/smartl/e906/figures/2.scons.png create mode 100644 bsp/xuantie/smartl/e906/figures/3.vscode.png create mode 100644 bsp/xuantie/smartl/e906/figures/4.run1.png create mode 100644 bsp/xuantie/smartl/e906/figures/5.run2.png create mode 100644 bsp/xuantie/smartl/e906/figures/6.cmd1.png create mode 100644 bsp/xuantie/smartl/e906/figures/7.cmd2.png create mode 100644 bsp/xuantie/smartl/e906/figures/8.cmd3.png create mode 100644 bsp/xuantie/smartl/e906/objdump.bat create mode 100644 bsp/xuantie/smartl/e906/qemu.bat create mode 100644 bsp/xuantie/smartl/e906/rtconfig.h create mode 100644 bsp/xuantie/smartl/e906/rtconfig.py diff --git a/bsp/xuantie/libraries/SConscript b/bsp/xuantie/libraries/SConscript new file mode 100644 index 00000000000..20f7689c53c --- /dev/null +++ b/bsp/xuantie/libraries/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/xuantie/libraries/device_drivers/SConscript b/bsp/xuantie/libraries/device_drivers/SConscript new file mode 100644 index 00000000000..6b20603694e --- /dev/null +++ b/bsp/xuantie/libraries/device_drivers/SConscript @@ -0,0 +1,16 @@ +from building import * +import os + +cwd = GetCurrentDir() +CPPPATH = [cwd] + +src = Split(""" +""") + +if GetDepend('SOC_XUANTIE'): + + if GetDepend('BSP_USING_UART'): + src += ['drv_usart.c'] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) +Return('group') diff --git a/bsp/xuantie/libraries/device_drivers/drv_usart.c b/bsp/xuantie/libraries/device_drivers/drv_usart.c new file mode 100644 index 00000000000..677ba579d61 --- /dev/null +++ b/bsp/xuantie/libraries/device_drivers/drv_usart.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-27 WangShun the first version + */ + +#include "board.h" +#include "rtthread.h" +#include +#include +#include + +#ifdef RT_USING_SERIAL + #define DRV_DEBUG + #define LOG_TAG "drv.uart" + + #ifdef DRV_DEBUG + #define DBG_LVL DBG_LOG + #else + #define DBG_LVL DBG_INFO + #endif /* DRV_DEBUG */ + + #include + + #if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3) \ + && !defined(BSP_USING_UART4) && !defined(BSP_USING_UART5) && !defined(BSP_USING_UART6) && !defined(BSP_USING_UART7) + #error "Please define at least one BSP_USING_UARTx" + /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ + #endif + +static void xuantie_uart0_rx_isr(csi_uart_t *uart_handler, csi_uart_event_t event, void *arg); + +enum +{ +#ifdef BSP_USING_UART0 + UART0_INDEX, +#endif +}; + +struct xuantie_uart_config uart_config[] = +{ +#ifdef BSP_USING_UART0 + { + "uart0", + 0, + xuantie_uart0_rx_isr + } +#endif +}; + +struct xuantie_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0}; + +static rt_err_t xuantie_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct xuantie_uart *uart = (struct xuantie_uart *)serial->parent.user_data; + csi_error_t ret; + + ret = csi_uart_baud(&uart->uart, cfg->baud_rate); + if (ret != CSI_OK) + { + return -RT_ERROR; + } + + csi_uart_data_bits_t data_bits; + csi_uart_parity_t parity; + csi_uart_stop_bits_t stop_bits; + + switch (cfg->data_bits) + { + case DATA_BITS_5: + data_bits = UART_DATA_BITS_5; + break; + case DATA_BITS_6: + data_bits = UART_DATA_BITS_6; + break; + case DATA_BITS_7: + data_bits = UART_DATA_BITS_7; + break; + case DATA_BITS_8: + data_bits = UART_DATA_BITS_8; + break; + case DATA_BITS_9: + data_bits = UART_DATA_BITS_9; + break; + default: + data_bits = UART_DATA_BITS_8; + break; + } + + switch (cfg->parity) + { + case PARITY_NONE: + parity = UART_PARITY_NONE; + break; + case PARITY_ODD: + parity = UART_PARITY_ODD; + break; + case PARITY_EVEN: + parity = UART_PARITY_EVEN; + break; + default: + parity = UART_PARITY_NONE; + break; + } + + switch (cfg->stop_bits) + { + case STOP_BITS_1: + stop_bits = UART_STOP_BITS_1; + break; + case STOP_BITS_2: + stop_bits = UART_STOP_BITS_2; + break; + default: + stop_bits = UART_STOP_BITS_1; + break; + } + + ret = csi_uart_format(&uart->uart, data_bits, parity, stop_bits); + if (ret != CSI_OK) + { + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t xuantie_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + switch (cmd) + { + case RT_DEVICE_CTRL_CONFIG: + return xuantie_configure(serial, (struct serial_configure *)arg); + default: + return -RT_ERROR; + } +} + +static int xuantie_putc(struct rt_serial_device *serial, char c) +{ + struct xuantie_uart *uart = (struct xuantie_uart *)serial->parent.user_data; + int32_t ret; + + ret = csi_uart_send(&uart->uart, &c, 1, 50); + if (ret == 1) + return RT_EOK; + + return -RT_ERROR; +} + +static int xuantie_getc(struct rt_serial_device *serial) +{ + int c = -1; + struct xuantie_uart *uart = (struct xuantie_uart *)serial->parent.user_data; + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE((&uart->uart)); + + csi_uart_receive(&uart->uart, &c, 1, 0x5); + dw_uart_enable_recv_irq(uart_base); + return c; +} + +static const struct rt_uart_ops xuantie_uart_ops = +{ + xuantie_configure, + xuantie_control, + xuantie_putc, + xuantie_getc, + RT_NULL, +}; + +static void xuantie_uart0_rx_isr(csi_uart_t *uart_handler, csi_uart_event_t event, void *arg) +{ + rt_interrupt_enter(); + rt_hw_serial_isr(&uart_obj[UART0_INDEX].serial, RT_SERIAL_EVENT_RX_IND); + rt_interrupt_leave(); +} + +int rt_hw_usart_init(void) +{ + rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct xuantie_uart); + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + rt_err_t result = 0; + + for (int i = 0; i < obj_num; i++) + { + /* Initialize YOC UART */ + result = csi_uart_init(&uart_obj[i].uart, 0); + if (result != CSI_OK) + { + LOG_E("Failed to initialize UART %d", uart_obj[i].config->idx); + return -RT_ERROR; + } + + /* Init UART object */ + uart_obj[i].config = &uart_config[i]; + uart_obj[i].serial.ops = &xuantie_uart_ops; + uart_obj[i].serial.config = config; + + csi_uart_attach_callback(&uart_obj[i].uart, uart_obj[i].config->xuantie_uart_rx_isr, NULL); + + /* Register UART device */ + result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name, + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + &uart_obj[i]); + if (result != RT_EOK) + { + LOG_E("Failed to register UART device %s", uart_obj[i].config->name); + csi_uart_uninit(&uart_obj[i].uart); + return -RT_ERROR; + } + } + return result; +} + +#endif /* RT_USING_SERIAL */ diff --git a/bsp/xuantie/libraries/device_drivers/drv_usart.h b/bsp/xuantie/libraries/device_drivers/drv_usart.h new file mode 100644 index 00000000000..f18fd544688 --- /dev/null +++ b/bsp/xuantie/libraries/device_drivers/drv_usart.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-12-08 WangShun the first version + */ +#ifndef __DRV_USART_H__ +#define __DRV_USART_H__ +#include +#include "rtdevice.h" +#include + +#include +#include +#include + +/* xuantie config class */ +struct xuantie_uart_config +{ + const char *name; + uint32_t idx; + void (*xuantie_uart_rx_isr)(csi_uart_t *uart_handler, csi_uart_event_t event, void *arg); +}; + +/* xuantie uart dirver class */ +struct xuantie_uart +{ + struct xuantie_uart_config *config; + struct rt_serial_device serial; + csi_uart_t uart; +}; + +extern void uart_rx_isr (void *id); +int rt_hw_usart_init(void); +#endif /* __DRV_USART_H__ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/SConscript b/bsp/xuantie/libraries/xuantie_libraries/SConscript new file mode 100644 index 00000000000..20f7689c53c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/SConscript b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/SConscript new file mode 100644 index 00000000000..20f7689c53c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_smartl.ld b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_smartl.ld new file mode 100644 index 00000000000..ac715758b2c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_smartl.ld @@ -0,0 +1,259 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file gcc_csky.ld + * @brief csky linker file + * @version V1.0 + * @date 02. June 2017 + ******************************************************************************/ +MEMORY +{ + ISRAM : ORIGIN = 0x00000000 , LENGTH = 0x20000 /* ISRAM 128KB*/ + DSRAM : ORIGIN = 0x20000000 , LENGTH = 0x80000 /* DSRAM 512KB*/ + SRAM : ORIGIN = 0x60000000 , LENGTH = 0x20000 /* SRAM 128KB, no cacheable*/ +} + +__min_heap_size = 0x200; +PROVIDE (__ram_end = 0x20080000); +PROVIDE (__heap_end = __ram_end); + +REGION_ALIAS("REGION_TEXT", ISRAM); +REGION_ALIAS("REGION_RODATA", ISRAM); +REGION_ALIAS("REGION_DATA", DSRAM); +REGION_ALIAS("REGION_BSS", DSRAM); + +ENTRY(Reset_Handler) +SECTIONS +{ + .text : { + . = ALIGN(0x4) ; + __stext = . ; + KEEP(*startup.o(*.text)) + KEEP(*startup.o(*.vectors)) + KEEP(*vectors.o(*.text)) + KEEP(*(.text.entry)) + *(.text*) + *(.gnu.warning) + *(.stub) + *(.gnu.linkonce.t*) + *(.glue_7t) + *(.glue_7) + *(.jcr) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN (0x4) ; + PROVIDE(__ctbp = .); + *(.call_table_data) + *(.call_table_text) + . = ALIGN(0x10) ; + __etext = . ; + } > REGION_TEXT + .rodata : { + . = ALIGN(0x4) ; + __srodata = .; + *(.rdata) + *(.rdata*) + *(.rdata1) + *(.rdata.*) + *(.rodata*) + *(.srodata*) + . = ALIGN(0x4) ; + __init_array_start = .; + __ctors_start__ = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + __ctors_end__ = .; + + __fini_array_start = .; + __dtors_start__ = .; + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + __fini_array_end = .; + __dtors_end__ = .; + . = ALIGN(0x4) ; + + __ctor_start__ = .; + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __ctor_end__ = .; + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __dtor_end__ = .; + . = ALIGN(0x4) ; +/*****************************************/ + /* section information for finsh shell */ + . = ALIGN(0x4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(0x4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(0x4); + + /* section information for initial. */ + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(0x4) ; + + /* section information for at utest */ + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + . = ALIGN(0x4); + + /* section information for at server */ + . = ALIGN(0x4); + __rtatcmdtab_start = .; + KEEP(*(RtAtCmdTab)) + __rtatcmdtab_end = .; + . = ALIGN(0x4); + + /* section information for modules */ + . = ALIGN(0x4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + + /* section information for uPRC */ + . = ALIGN(0x4); + __uRPCSvcTab_start = .; + KEEP(*(uRPCSvcTab)) + __uRPCSvcTab_end = .; + + /* section information for var export */ + . = ALIGN(0x4); + __ve_table_start = .; + KEEP(*(SORT(*.VarExpTab.*))) + __ve_table_end = .; +/*****************************************/ +/************** added drivers **************/ + _cli_region_begin = .; + KEEP(*(CliRegion)) + . = ALIGN(0x4); + _cli_region_end = .; + + __core_driver_start__ = .; + KEEP(*(.core_driver_entry)) + . = ALIGN(0x4); + __core_driver_end__ = .; + + __bus_driver_start__ = .; + KEEP(*(*.bus_driver_entry)) + __bus_driver_end__ = .; + + __early_driver_start__ = .; + KEEP(*(*.early_driver_entry)) + __early_driver_end__ = .; + + __vfs_driver_start__ = .; + KEEP(*(*.vfs_driver_entry)) + __vfs_driver_end__ = .; + + __level0_driver_start__ = .; + KEEP(*(*.level0_driver_entry)) + __level0_driver_end__ = .; + + __level1_driver_start__ = .; + KEEP(*(*.level1_driver_entry)) + __level1_driver_end__ = .; + + __level2_driver_start__ = .; + KEEP(*(*.level2_driver_entry)) + __level2_driver_end__ = .; + + __level3_driver_start__ = .; + KEEP(*(*.level3_driver_entry)) + __level3_driver_end__ = .; + + __post_driver_start__ = .; + KEEP(*(*.post_driver_entry)) + __post_driver_end__ = .; +/************** end of drivers *********/ + . = ALIGN(0x4) ; + __erodata = .; + __rodata_end__ = .; + } > REGION_RODATA + .data : { + . = ALIGN(0x4) ; + __sdata = . ; + __data_start__ = . ; + data_start = . ; + *(.got.plt) + *(.got) + *(.gnu.linkonce.r*) + *(.data*) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + __start_init_call = .; + *(.initcall.init) + __stop_init_call = .; + __start_cmd = .; + *(.bootloaddata.cmd) + . = ALIGN(0x4) ; + __stop_cmd = .; + __global_pointer$ = .; + *(.sdata) + *(.sdata.*) + *(.sdata2.*) + *(.gnu.linkonce.s.*) + *(__libc_atexit) + *(__libc_subinit) + *(__libc_subfreeres) + *(.note.ABI-tag) + . = ALIGN(0x4) ; + __edata = .; + __data_end__ = .; + } > REGION_DATA AT > REGION_RODATA + ._ram_code : { + . = ALIGN(0x4) ; + __ram_code_start__ = .; + *(.ram.code*) + . = ALIGN(0x4) ; + __ram_code_end__ = .; + } > REGION_DATA AT > REGION_RODATA + .bss : { + . = ALIGN(0x4) ; + __sbss = ALIGN(0x4) ; + __bss_start__ = . ; + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.dynbss) + *(.bss*) + *(COMMON) + . = ALIGN(0x4) ; + __ebss = . ; + __bss_end__ = .; + __end = . ; + end = . ; + } > REGION_BSS AT > REGION_BSS + ._user_heap (NOLOAD): { + . = ALIGN(0x4) ; + *(.stack*) + . = ALIGN(0x4) ; + __heap_start = .; + . += __min_heap_size; + . = ALIGN(0x4) ; + } > REGION_BSS AT > REGION_BSS +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_xiaohui.ld b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_xiaohui.ld new file mode 100644 index 00000000000..ea255d2035b --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_xiaohui.ld @@ -0,0 +1,268 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +MEMORY +{ + DRAM : ORIGIN = 0x50000000, LENGTH = 0x100000 /* on-chip DRAM 1*1MB */ +} + +__min_heap_size = 0x200; +PROVIDE (__ram_end = 0x50100000 - 0x8); +PROVIDE (__heap_end = __ram_end); + +REGION_ALIAS("REGION_TEXT", DRAM); +REGION_ALIAS("REGION_RODATA", DRAM); +REGION_ALIAS("REGION_DATA", DRAM); +REGION_ALIAS("REGION_BSS", DRAM); + +ENTRY(Reset_Handler) +SECTIONS +{ + .text : { + . = ALIGN(0x4) ; + __stext = . ; + KEEP(*startup.o(*.text)) + KEEP(*startup.o(*.vectors)) + KEEP(*vectors.o(*.text)) + KEEP(*(.text.entry)) + *(.text) + *(.text*) + *(.text.*) + *(.gnu.warning) + *(.stub) + *(.gnu.linkonce.t*) + *(.glue_7t) + *(.glue_7) + *(.jcr) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(0x4) ; + PROVIDE(__ctbp = .); + *(.call_table_data) + *(.call_table_text) + . = ALIGN(0x4) ; + __etext = . ; + } > REGION_TEXT + .gcc_except_table : ONLY_IF_RO { + *(.gcc_except_table .gcc_except_table.*) + } > REGION_TEXT + .rodata : { + . = ALIGN(0x4) ; + __srodata = .; + *(.rdata) + *(.rdata*) + *(.rdata1) + *(.rdata.*) + *(.rodata) + *(.rodata1) + *(.rodata*) + *(.rodata.*) + *(.rodata.str1.4) + *(.srodata*) + . = ALIGN(0x8) ; + + __init_array_start = .; + __ctors_start__ = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + __ctors_end__ = .; + + . = ALIGN(0x8) ; + __fini_array_start = .; + __dtors_start__ = .; + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + __fini_array_end = .; + __dtors_end__ = .; + + . = ALIGN(0x8) ; + __ctor_start__ = .; + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __ctor_end__ = .; + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __dtor_end__ = .; + . = ALIGN(0x4) ; +/*****************************************/ + /* section information for finsh shell */ + . = ALIGN(0x4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(0x4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(0x4); + + /* section information for initial. */ + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(0x4) ; + + /* section information for at utest */ + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + . = ALIGN(0x4); + + /* section information for at server */ + . = ALIGN(0x4); + __rtatcmdtab_start = .; + KEEP(*(RtAtCmdTab)) + __rtatcmdtab_end = .; + . = ALIGN(0x4); + + /* section information for modules */ + . = ALIGN(0x4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + + /* section information for uPRC */ + . = ALIGN(0x4); + __uRPCSvcTab_start = .; + KEEP(*(uRPCSvcTab)) + __uRPCSvcTab_end = .; + + /* section information for var export */ + . = ALIGN(0x4); + __ve_table_start = .; + KEEP(*(SORT(*.VarExpTab.*))) + __ve_table_end = .; +/*****************************************/ +/************** added drivers **************/ + _cli_region_begin = .; + KEEP(*(CliRegion)) + . = ALIGN(0x4) ; + _cli_region_end = .; + + __core_driver_start__ = .; + KEEP(*(.core_driver_entry)) + . = ALIGN(0x4) ; + __core_driver_end__ = .; + + __bus_driver_start__ = .; + KEEP(*(*.bus_driver_entry)) + __bus_driver_end__ = .; + + __early_driver_start__ = .; + KEEP(*(*.early_driver_entry)) + __early_driver_end__ = .; + + __vfs_driver_start__ = .; + KEEP(*(*.vfs_driver_entry)) + __vfs_driver_end__ = .; + + __level0_driver_start__ = .; + KEEP(*(*.level0_driver_entry)) + __level0_driver_end__ = .; + + __level1_driver_start__ = .; + KEEP(*(*.level1_driver_entry)) + __level1_driver_end__ = .; + + __level2_driver_start__ = .; + KEEP(*(*.level2_driver_entry)) + __level2_driver_end__ = .; + + __level3_driver_start__ = .; + KEEP(*(*.level3_driver_entry)) + __level3_driver_end__ = .; + + __post_driver_start__ = .; + KEEP(*(*.post_driver_entry)) + __post_driver_end__ = .; +/************** end of drivers *********/ + . = ALIGN(0x4) ; + __erodata = .; + __rodata_end__ = .; + } > REGION_RODATA + .data : { + . = ALIGN(0x4) ; + __sdata = . ; + __data_start__ = . ; + data_start = . ; + *(.got.plt) + *(.got) + *(.gnu.linkonce.r*) + *(.data) + *(.data*) + *(.data1) + *(.data.*) + *(.gnu.linkonce.d*) + *(.data1) + *(.gcc_except_table) + *(.gcc_except_table*) + __start_init_call = .; + *(.initcall.init) + __stop_init_call = .; + __start_cmd = .; + *(.bootloaddata.cmd) + . = ALIGN(4) ; + __stop_cmd = .; + __global_pointer$ = .; + *(.sdata) + *(.sdata.*) + *(.sdata2.*) + *(.gnu.linkonce.s.*) + *(__libc_atexit) + *(__libc_subinit) + *(__libc_subfreeres) + *(.note.ABI-tag) + . = ALIGN(0x4) ; + __edata = .; + __data_end__ = .; + } > REGION_DATA + ._ram_code : { + . = ALIGN(0x4) ; + __ram_code_start__ = .; + *(.ram.code*) + . = ALIGN(0x4) ; + __ram_code_end__ = .; + } > REGION_DATA + .bss : { + . = ALIGN(0x4) ; + __sbss = ALIGN(0x4) ; + __bss_start__ = . ; + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(0x4) ; + __ebss = . ; + __bss_end__ = .; + __end = . ; + end = . ; + } > REGION_BSS + ._user_heap (NOLOAD): { + . = ALIGN(0x4) ; + *(.stack*) + . = ALIGN(0x4) ; + __heap_start = .; + . += __min_heap_size; + . = ALIGN(0x4) ; + } > REGION_BSS +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_xiaohui.ld.sram b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_xiaohui.ld.sram new file mode 100644 index 00000000000..8c1fd9eb398 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_xiaohui.ld.sram @@ -0,0 +1,264 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +MEMORY +{ + DRAM : ORIGIN = 0x00000000, LENGTH = 0x100000 /* on-chip SRAM 1*1MB */ +} + +__min_heap_size = 0x200; +PROVIDE (__ram_end = 0x00100000 - 0x8); +PROVIDE (__heap_end = __ram_end); + +REGION_ALIAS("REGION_TEXT", DRAM); +REGION_ALIAS("REGION_RODATA", DRAM); +REGION_ALIAS("REGION_DATA", DRAM); +REGION_ALIAS("REGION_BSS", DRAM); + +ENTRY(Reset_Handler) +SECTIONS +{ + .text : { + . = ALIGN(0x4) ; + __stext = . ; + KEEP(*startup.o(*.text)) + KEEP(*startup.o(*.vectors)) + KEEP(*vectors.o(*.text)) + KEEP(*(.text.entry)) + *(.text) + *(.text*) + *(.text.*) + *(.gnu.warning) + *(.stub) + *(.gnu.linkonce.t*) + *(.glue_7t) + *(.glue_7) + *(.jcr) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(0x4) ; + PROVIDE(__ctbp = .); + *(.call_table_data) + *(.call_table_text) + . = ALIGN(0x4) ; + __etext = . ; + } > REGION_TEXT + .gcc_except_table : ONLY_IF_RO { + *(.gcc_except_table .gcc_except_table.*) + } > REGION_TEXT + .rodata : { + . = ALIGN(0x4) ; + __srodata = .; + *(.rdata) + *(.rdata*) + *(.rdata1) + *(.rdata.*) + *(.rodata) + *(.rodata1) + *(.rodata*) + *(.rodata.*) + *(.rodata.str1.4) + *(.srodata*) + . = ALIGN(0x4) ; + + __init_array_start = .; + __ctors_start__ = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + __ctors_end__ = .; + + __fini_array_start = .; + __dtors_start__ = .; + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + __fini_array_end = .; + __dtors_end__ = .; + + __ctor_start__ = .; + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __ctor_end__ = .; + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __dtor_end__ = .; + . = ALIGN(0x4) ; +/*****************************************/ + /* section information for finsh shell */ + . = ALIGN(0x4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(0x4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(0x4); + + /* section information for initial. */ + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(0x4) ; + + /* section information for at utest */ + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + . = ALIGN(0x4); + + /* section information for at server */ + . = ALIGN(0x4); + __rtatcmdtab_start = .; + KEEP(*(RtAtCmdTab)) + __rtatcmdtab_end = .; + . = ALIGN(0x4); + + /* section information for modules */ + . = ALIGN(0x4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + + /* section information for uPRC */ + . = ALIGN(0x4); + __uRPCSvcTab_start = .; + KEEP(*(uRPCSvcTab)) + __uRPCSvcTab_end = .; + + /* section information for var export */ + . = ALIGN(0x4); + __ve_table_start = .; + KEEP(*(SORT(*.VarExpTab.*))) + __ve_table_end = .; +/*****************************************/ +/************** added drivers **************/ + _cli_region_begin = .; + KEEP(*(CliRegion)) + . = ALIGN(0x4) ; + _cli_region_end = .; + + __core_driver_start__ = .; + KEEP(*(.core_driver_entry)) + . = ALIGN(0x4) ; + __core_driver_end__ = .; + + __bus_driver_start__ = .; + KEEP(*(*.bus_driver_entry)) + __bus_driver_end__ = .; + + __early_driver_start__ = .; + KEEP(*(*.early_driver_entry)) + __early_driver_end__ = .; + + __vfs_driver_start__ = .; + KEEP(*(*.vfs_driver_entry)) + __vfs_driver_end__ = .; + + __level0_driver_start__ = .; + KEEP(*(*.level0_driver_entry)) + __level0_driver_end__ = .; + + __level1_driver_start__ = .; + KEEP(*(*.level1_driver_entry)) + __level1_driver_end__ = .; + + __level2_driver_start__ = .; + KEEP(*(*.level2_driver_entry)) + __level2_driver_end__ = .; + + __level3_driver_start__ = .; + KEEP(*(*.level3_driver_entry)) + __level3_driver_end__ = .; + + __post_driver_start__ = .; + KEEP(*(*.post_driver_entry)) + __post_driver_end__ = .; +/************** end of drivers *********/ + . = ALIGN(0x4) ; + __erodata = .; + __rodata_end__ = .; + } > REGION_RODATA + .data : { + . = ALIGN(0x4) ; + __sdata = . ; + __data_start__ = . ; + data_start = . ; + *(.got.plt) + *(.got) + *(.gnu.linkonce.r*) + *(.data) + *(.data*) + *(.data1) + *(.data.*) + *(.gnu.linkonce.d*) + *(.data1) + *(.gcc_except_table) + *(.gcc_except_table*) + __start_init_call = .; + *(.initcall.init) + __stop_init_call = .; + __start_cmd = .; + *(.bootloaddata.cmd) + . = ALIGN(4) ; + __stop_cmd = .; + __global_pointer$ = .; + *(.sdata) + *(.sdata.*) + *(.sdata2.*) + *(.gnu.linkonce.s.*) + *(__libc_atexit) + *(__libc_subinit) + *(__libc_subfreeres) + *(.note.ABI-tag) + __edata = .; + __data_end__ = .; + . = ALIGN(0x4) ; + } > REGION_DATA + .gcc_except_table : ONLY_IF_RW { + *(.gcc_except_table .gcc_except_table.*) + __edata = .; + __data_end__ = .; + } > REGION_DATA + .bss : { + . = ALIGN(0x4) ; + __sbss = ALIGN(0x4) ; + __bss_start__ = . ; + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(0x4) ; + __ebss = . ; + __bss_end__ = .; + __end = . ; + end = . ; + } > REGION_BSS + ._user_heap (NOLOAD): { + . = ALIGN(0x4) ; + *(.stack*) + . = ALIGN(0x4) ; + __heap_start = .; + . += __min_heap_size; + . = ALIGN(0x4) ; + } > REGION_BSS +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/SConscript b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/SConscript new file mode 100644 index 00000000000..9fa163b0b72 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/SConscript @@ -0,0 +1,13 @@ +from building import * +import os + +cwd = GetCurrentDir() +CPPPATH = [cwd] +CPPPATH += [cwd + '/asm'] +CPPPATH += [cwd + '/drv'] + +src = Split(""" +""") + +group = DefineGroup('dummy_inc', src, depend = [''], CPPPATH = CPPPATH) +Return('group') diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/asm/riscv_asm_macro.h b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/asm/riscv_asm_macro.h new file mode 100644 index 00000000000..4eeded81677 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/asm/riscv_asm_macro.h @@ -0,0 +1,598 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/* + * attention: don't modify this file as a suggest + * you should copy from chip_riscv_dummy/include/asm/riscv_asm_macro.h and keep it newer + * please contact xuantie-rtos os team if have question + */ + +#ifndef __RISCV_ASM_MACRO_H__ +#define __RISCV_ASM_MACRO_H__ + +#if (!defined(__riscv_flen)) && (CONFIG_CHECK_FPU_DIRTY) +#error "this cpu doesn't supprot FPU, but macro 'CONFIG_CHECK_FPU_DIRTY' is defined, please remove it." +#endif + +#if (!defined(__riscv_vector)) && (CONFIG_CHECK_VECTOR_DIRTY) +#error "this cpu doesn't supprot vector, but macro 'CONFIG_CHECK_VECTOR_DIRTY' is defined, please remove it." +#endif + +#if (!defined(__riscv_matrix) && !defined(__riscv_xtheadmatrix)) && (CONFIG_CHECK_MATRIX_DIRTY) +#error "this cpu doesn't supprot matrix, but macro 'CONFIG_CHECK_MATRIX_DIRTY' is defined, please remove it." +#endif + +#include "riscv_csr.h" + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY +.macro RESTORE_MSTATUS + /* t0 and t1 are not restored before using */ + /* now, sp is at the top of the stack (the lowest address)*/ + li t1, 0 +#if __riscv_matrix || __riscv_xtheadmatrix /* matrix registers */ +#if __riscv_xlen == 64 + addi t1, t1, (12 + 12) +#else + addi t1, t1, 12 +#endif /*__riscv_xlen */ + csrr t0, xmlenb + slli t0, t0, 3 + add t1, t1, t0 +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + +#ifdef __riscv_vector /* vector registers */ + csrr t0, vlenb + slli t0, t0, 5 + add t1, t1, t0 +#if __riscv_xlen == 64 + addi t1, t1, (20+20) +#else + addi t1, t1, 20 +#endif /* __riscv_xlen */ +#endif /* __riscv_vector */ + +#if __riscv_flen == 64 /* float registers */ +#if __riscv_xlen == 64 + addi t1, t1, 168 +#else + addi t1, t1, 164 +#endif /* __riscv_xlen */ + +#elif __riscv_flen == 32 + addi t1, t1, 84 +#endif /* __riscv_flen */ + +#ifdef __riscv_dsp /* vxsat register, 32-bit cpu only */ + addi t1, t1, 4 +#endif /* __riscv_dsp */ + +#if __riscv_xlen == 64 /*general purpose registers*/ + addi t1, t1, (72 + 72) +#elif __riscv_xlen == 32 + addi t1, t1, 72 +#endif + add sp, sp, t1 + + /* now, sp is the position of mstatus */ + load_x t3, (0)(sp) + csrw mstatus, t3 + sub sp, sp, t1 +.endm + +.macro RESTORE_SSTATUS + /* t0 and t1 are not restored before using */ + /* now, sp is at the top of the stack (the lowest address)*/ + li t1, 0 +#if __riscv_matrix || __riscv_xtheadmatrix /* matrix registers */ +#if __riscv_xlen == 64 + addi t1, t1, (12 + 12) +#else + addi t1, t1, 12 +#endif /*__riscv_xlen */ + csrr t0, xmlenb + slli t0, t0, 3 + add t1, t1, t0 +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + +#ifdef __riscv_vector /* vector registers */ + csrr t0, vlenb + slli t0, t0, 5 + add t1, t1, t0 +#if __riscv_xlen == 64 + addi t1, t1, (20+20) +#else + addi t1, t1, 20 +#endif /* __riscv_xlen */ +#endif /* __riscv_vector */ + +#if __riscv_flen == 64 /* float registers */ +#if __riscv_xlen == 64 + addi t1, t1, 168 +#else + addi t1, t1, 164 +#endif /* __riscv_xlen */ + +#elif __riscv_flen == 32 + addi t1, t1, 84 +#endif /* __riscv_flen */ + +#if __riscv_xlen == 64 /*general purpose registers*/ + addi t1, t1, (72 + 72) +#elif __riscv_xlen == 32 + addi t1, t1, 72 +#endif + add sp, sp, t1 + + /* now, sp is the position of mstatus */ + load_x t3, (0)(sp) + csrw sstatus, t3 + sub sp, sp, t1 +.endm + +#endif /* CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY */ + +.macro SAVE_VECTOR_REGISTERS + /* t0,t1 saved before using */ + /* mstatus->t3 */ +#ifdef __riscv_vector +#if CONFIG_CHECK_VECTOR_DIRTY + /* check if VS filed of MSTATUS is 'dirty' */ + li t1, SR_VS_DIRTY + and t4, t3, t1 + bne t4, t1, 1f +#endif /* CONFIG_CHECK_VECTOR_DIRTY */ + + /* if dirty, save vector registers */ +#if __riscv_xlen == 64 + addi sp, sp, -(20+20) + csrr t0, vl + store_x t0, (0 +0 )(sp) + csrr t0, vtype + store_x t0, (4 +4 )(sp) + csrr t0, vstart + store_x t0, (8 +8 )(sp) + csrr t0, vxsat + store_x t0, (12 +12 )(sp) + csrr t0, vxrm + store_x t0, (16 +16 )(sp) +#else + addi sp, sp, -20 + csrr t0, vl + store_x t0, (0)(sp) + csrr t0, vtype + store_x t0, (4)(sp) + csrr t0, vstart + store_x t0, (8)(sp) + csrr t0, vxsat + store_x t0, (12)(sp) + csrr t0, vxrm + store_x t0, (16)(sp) +#endif /*__riscv_xlen */ + + csrr t0, vlenb + slli t0, t0, 3 + slli t1, t0, 2 + sub sp, sp, t1 +#if (__riscv_v == 7000) + vsetvli zero, zero, e8, m8 + vsb.v v0, (sp) + add sp, sp, t0 + vsb.v v8, (sp) + add sp, sp, t0 + vsb.v v16, (sp) + add sp, sp, t0 + vsb.v v24, (sp) +#elif (__riscv_v == 1000000) + vsetvli zero, zero, e8, m8, ta, ma + vs8r.v v0, (sp) + add sp, sp, t0 + vs8r.v v8, (sp) + add sp, sp, t0 + vs8r.v v16, (sp) + add sp, sp, t0 + vs8r.v v24, (sp) +#endif + sub t0, t1, t0 + sub sp, sp, t0 +#if CONFIG_CHECK_VECTOR_DIRTY + j 2f +1: /* don't need to save vector registers, set sp */ +#if __riscv_xlen == 64 + addi sp, sp, -(20+20) +#else + addi sp, sp, -20 +#endif + csrr t0, vlenb + slli t0, t0, 5 + sub sp, sp, t0 +2: +#endif /* CONFIG_CHECK_VECTOR_DIRTY */ +#endif /*__riscv_vector*/ +.endm + +.macro RESTORE_VECTOR_REGISTERS + /* t0,t1,t2 not restored before using, mstatus has been restored before using */ +#ifdef __riscv_vector +#if CONFIG_CHECK_VECTOR_DIRTY + /* check if VS filed of MSTATUS is 'dirty' */ + li t1, SR_VS_DIRTY + and t4, t3, t1 + bne t4, t1, 1f +#endif /* CONFIG_CHECK_VECTOR_DIRTY */ + + /* get the range of register */ + csrr t0, vlenb + slli t0, t0, 3 + + /* save */ +#if (__riscv_v == 7000) + vsetvli zero, zero, e8, m8 + vlb.v v0, (sp) + add sp, sp, t0 + vlb.v v8, (sp) + add sp, sp, t0 + vlb.v v16, (sp) + add sp, sp, t0 + vlb.v v24, (sp) + add sp, sp, t0 +#elif (__riscv_v == 1000000) + vsetvli zero, zero, e8, m8, ta, ma + vl8r.v v0, (sp) + add sp, sp, t0 + vl8r.v v8, (sp) + add sp, sp, t0 + vl8r.v v16, (sp) + add sp, sp, t0 + vl8r.v v24, (sp) + add sp, sp, t0 +#endif +#if __riscv_xlen == 64 + load_x t0, (0 +0)(sp) + load_x t1, (4 +4)(sp) + load_x t2, (8 +8)(sp) + vsetvl zero, t0, t1 + csrw vstart, t2 + load_x t2, (12 +12)(sp) + csrw vxsat, t2 + load_x t2, (16 +16)(sp) + csrw vxrm, t2 + addi sp, sp, (20+20) +#else + load_x t0, (0)(sp) + load_x t1, (4)(sp) + load_x t2, (8)(sp) + vsetvl zero, t0, t1 + csrw vstart, t2 + load_x t2, (12)(sp) + csrw vxsat, t2 + load_x t2, (16)(sp) + csrw vxrm, t2 + addi sp, sp, 20 +#endif /*__riscv_xlen */ +#if CONFIG_CHECK_VECTOR_DIRTY + j 2f +1: + /* don't restore, move sp only */ +#if __riscv_xlen == 64 + addi sp, sp, (20+20) +#else + addi sp, sp, (20) +#endif + csrr t0, vlenb + slli t0, t0, 5 + add sp, sp, t0 +2: +#endif /* CONFIG_CHECK_VECTOR_DIRTY */ +#endif /*__riscv_vector*/ +.endm + + +.macro SAVE_FLOAT_REGISTERS + /* t0, t1 saved before using */ +#if __riscv_flen == 64 +#if CONFIG_CHECK_FPU_DIRTY + /* check if FS filed of MSTATUS is 'dirty' */ + li t1, SR_FS_DIRTY + and t4, t3, t1 + bne t4, t1, 1f +#endif /*CONFIG_CHECK_FPU_DIRTY*/ + + /* save */ +#if __riscv_xlen == 64 + addi sp, sp, -(4+4) + frcsr t0 + store_x t0, (0 +0 )(sp) +#else + addi sp, sp, -4 + frcsr t0 + store_x t0, 0(sp) +#endif /*__riscv_xlen */ + + addi sp, sp, -160 + fstore_x ft0, (0 +0 )(sp) + fstore_x ft1, (4 +4 )(sp) + fstore_x ft2, (8 +8 )(sp) + fstore_x ft3, (12+12)(sp) + fstore_x ft4, (16+16)(sp) + fstore_x ft5, (20+20)(sp) + fstore_x ft6, (24+24)(sp) + fstore_x ft7, (28+28)(sp) + fstore_x fa0, (32+32)(sp) + fstore_x fa1, (36+36)(sp) + fstore_x fa2, (40+40)(sp) + fstore_x fa3, (44+44)(sp) + fstore_x fa4, (48+48)(sp) + fstore_x fa5, (52+52)(sp) + fstore_x fa6, (56+56)(sp) + fstore_x fa7, (60+60)(sp) + fstore_x ft8, (64+64)(sp) + fstore_x ft9, (68+68)(sp) + fstore_x ft10,(72+72)(sp) + fstore_x ft11,(76+76)(sp) +#elif __riscv_flen == 32 +#if CONFIG_CHECK_FPU_DIRTY + /* check if FS filed of MSTATUS is 'dirty' */ + li t1, SR_FS_DIRTY + and t4, t3, t1 + bne t4, t1, 1f +#endif /* CONFIG_CHECK_FPU_DIRTY */ + + addi sp, sp, -4 + frcsr t0 + store_x t0, 0(sp) + + addi sp, sp, -80 + fstore_x ft0, 0(sp) + fstore_x ft1, 4(sp) + fstore_x ft2, 8(sp) + fstore_x ft3, 12(sp) + fstore_x ft4, 16(sp) + fstore_x ft5, 20(sp) + fstore_x ft6, 24(sp) + fstore_x ft7, 28(sp) + fstore_x fa0, 32(sp) + fstore_x fa1, 36(sp) + fstore_x fa2, 40(sp) + fstore_x fa3, 44(sp) + fstore_x fa4, 48(sp) + fstore_x fa5, 52(sp) + fstore_x fa6, 56(sp) + fstore_x fa7, 60(sp) + fstore_x ft8, 64(sp) + fstore_x ft9, 68(sp) + fstore_x ft10,72(sp) + fstore_x ft11,76(sp) +#endif /*__riscv_flen */ +#if CONFIG_CHECK_FPU_DIRTY + j 2f +1: + /* don't store, move sp only */ +#if __riscv_flen == 64 +#if __riscv_xlen == 64 + addi sp, sp, -168 +#else + addi sp, sp, -164 +#endif /*__riscv_xlen */ +#elif __riscv_flen == 32 + addi sp, sp, -84 +#endif /* __riscv_xlen */ +2: +#endif +.endm + +.macro RESTORE_FLOAT_REGISTERS + /* t0 and t1 are not restored before using, mstatus has been restored before using */ +#if __riscv_flen == 64 +#if CONFIG_CHECK_FPU_DIRTY + /* check if FS filed of MSTATUS is 'dirty' */ + li t1, SR_FS_DIRTY + and t4, t3, t1 + bne t4, t1, 1f +#endif /* CONFIG_CHECK_FPU_DIRTY */ + + /* restore */ + fload_x ft0, (0 +0 )(sp) + fload_x ft1, (4 +4 )(sp) + fload_x ft2, (8 +8 )(sp) + fload_x ft3, (12+12)(sp) + fload_x ft4, (16+16)(sp) + fload_x ft5, (20+20)(sp) + fload_x ft6, (24+24)(sp) + fload_x ft7, (28+28)(sp) + fload_x fa0, (32+32)(sp) + fload_x fa1, (36+36)(sp) + fload_x fa2, (40+40)(sp) + fload_x fa3, (44+44)(sp) + fload_x fa4, (48+48)(sp) + fload_x fa5, (52+52)(sp) + fload_x fa6, (56+56)(sp) + fload_x fa7, (60+60)(sp) + fload_x ft8, (64+64)(sp) + fload_x ft9, (68+68)(sp) + fload_x ft10,(72+72)(sp) + fload_x ft11,(76+76)(sp) + addi sp, sp, 160 + +#if __riscv_xlen == 64 + load_x t0, (0 +0)(sp) + fscsr t0 + addi sp, sp, (4+4) +#else + load_x t0, 0(sp) + fscsr t0 + addi sp, sp, 4 +#endif /*__riscv_xlen */ +#elif __riscv_flen == 32 +#if CONFIG_CHECK_FPU_DIRTY + /* check if FS filed of MSTATUS is 'dirty' */ + li t1, SR_FS_DIRTY + and t4, t3, t1 + bne t4, t1, 1f +#endif /* CONFIG_CHECK_FPU_DIRTY */ + + /* restore */ + fload_x ft0, 0(sp) + fload_x ft1, 4(sp) + fload_x ft2, 8(sp) + fload_x ft3, 12(sp) + fload_x ft4, 16(sp) + fload_x ft5, 20(sp) + fload_x ft6, 24(sp) + fload_x ft7, 28(sp) + fload_x fa0, 32(sp) + fload_x fa1, 36(sp) + fload_x fa2, 40(sp) + fload_x fa3, 44(sp) + fload_x fa4, 48(sp) + fload_x fa5, 52(sp) + fload_x fa6, 56(sp) + fload_x fa7, 60(sp) + fload_x ft8, 64(sp) + fload_x ft9, 68(sp) + fload_x ft10,72(sp) + fload_x ft11,76(sp) + addi sp, sp, 80 + + load_x t0, 0(sp) + fscsr t0 + addi sp, sp, 4 +#endif /*__riscv_flen */ +#if CONFIG_CHECK_FPU_DIRTY + j 2f +1: + /* don't restore, move sp only */ +#if __riscv_flen == 64 +#if __riscv_xlen == 64 + addi sp, sp, 168 +#elif __riscv_xlen == 32 + addi sp, sp, 164 +#endif +#elif __riscv_flen == 32 + addi sp, sp, 84 +#endif /* __riscv_flen */ +2: +#endif /* CONFIG_CHECK_FPU_DIRTY */ +.endm + +.macro SAVE_MATRIX_REGISTERS + /* t0,t1 saved before using */ + +#if __riscv_matrix || __riscv_xtheadmatrix +#if CONFIG_CHECK_MATRIX_DIRTY + /* check if FS filed of MSTATUS is 'dirty' */ + li t1, SR_MS_DIRTY + and t4, t3, t1 + bne t4, t1, 1f +#endif /* CONFIG_CHECK_MATRIX_DIRTY */ + + /* store */ +#if __riscv_xlen == 64 + addi sp, sp, -(12+12) + csrr t0, xmrstart + store_x t0, (0 +0 )(sp) + csrr t0, xmcsr + store_x t0, (4 +4 )(sp) + csrr t0, xmsize + store_x t0, (8 +8 )(sp) +#else + addi sp, sp, -12 + csrr t0, xmrstart + store_x t0, (0)(sp) + csrr t0, xmcsr + store_x t0, (4)(sp) + csrr t0, xmsize + store_x t0, (8)(sp) +#endif /*__riscv_xlen */ + + csrr t0, xmlenb + slli t1, t0, 3 + sub sp, sp, t1 + csrw xmrstart, x0 + mst8mb m0, (sp) +#if CONFIG_CHECK_MATRIX_DIRTY + j 2f +1: + /* don't save, move sp only */ + csrr t0, xmlenb + slli t1, t0, 3 + sub sp, sp, t1 +#if __riscv_xlen == 64 + addi sp, sp, -24 +#else + addi sp, sp, -12 +#endif +2: +#endif /* CONFIG_CHECK_MATRIX_DIRTY */ +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ +.endm + +.macro RESTORE_MATRIX_REGISTERS + /* t0 and t1 are not restored before using, mstatus has been restored before using */ + +#if __riscv_matrix || __riscv_xtheadmatrix +#if CONFIG_CHECK_MATRIX_DIRTY + /* check if FS filed of MSTATUS is 'dirty' */ + li t1, SR_MS_DIRTY + and t4, t3, t1 + bne t4, t1, 1f +#endif /* CONFIG_CHECK_MATRIX_DIRTY */ + + /* restore */ + csrr t0, xmlenb + slli t1, t0, 3 + csrw xmrstart, x0 + mld8mb m0, (sp) + add sp, sp, t1 +#if __riscv_xlen == 64 + load_x t0, (0 + 0)(sp) + csrw xmrstart, t0 + load_x t0, (4 + 4)(sp) + csrw xmcsr, t0 + load_x t0, (8 + 8)(sp) + csrw xmsize, t0 + addi sp, sp, (12+12) +#else + load_x t0, (0)(sp) + csrw xmrstart, t0 + load_x t0, (4)(sp) + csrw xmcsr, t0 + load_x t0, (8)(sp) + csrw xmsize, t0 + addi sp, sp, 12 +#endif /*__riscv_xlen */ +#if CONFIG_CHECK_MATRIX_DIRTY + j 2f +1: + /* don't restore, move sp only */ + csrr t0, xmlenb + slli t1, t0, 3 + add sp, sp, t1 +#if __riscv_xlen == 64 + addi sp, sp, 24 +#else + addi sp, sp, 12 +#endif +2: +#endif /* CONFIG_CHECK_MATRIX_DIRTY */ +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ +.endm + + + +#endif /* __RISCV_ASM_MACRO_H__ */ + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/asm/riscv_csr.h b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/asm/riscv_csr.h new file mode 100644 index 00000000000..423db93afa2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/asm/riscv_csr.h @@ -0,0 +1,177 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/* + * attention: don't modify this file as a suggest + * you should copy from chip_riscv_dummy/include/asm/riscv_csr.h and keep it newer + * please contact xuantie-rtos os team if have question + */ + +#ifndef __RISCV_CSR_H__ +#define __RISCV_CSR_H__ + +#if __riscv_xlen == 64 + #define portWORD_SIZE 8 + #define store_x sd + #define load_x ld +#elif __riscv_xlen == 32 + #define store_x sw + #define load_x lw + #define portWORD_SIZE 4 +#else + #error Assembler did not define __riscv_xlen +#endif + +#if __riscv_flen == 64 + #define fstore_x fsd + #define fload_x fld +#elif __riscv_flen == 32 + #define fstore_x fsw + #define fload_x flw +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE +#define MODE_PREFIX(suffix) s##suffix +#else +#define MODE_PREFIX(suffix) m##suffix +#endif + +/* Status register flags */ +#define SR_SIE 0x00000002UL /* Supervisor Interrupt Enable */ +#define SR_MIE 0x00000008UL /* Machine Interrupt Enable */ +#define SR_SPIE 0x00000020UL /* Previous Supervisor IE */ +#define SR_MPIE 0x00000080UL /* Previous Machine IE */ +#define SR_SPP_U 0x00000000UL /* Previously User mode */ +#define SR_SPP_S 0x00000100UL /* Previously Supervisor mode */ +#define SR_MPP_U 0x00000000UL /* Previously User mode */ +#define SR_MPP_S 0x00000800UL /* Previously Supervisor mode */ +#define SR_MPP_M 0x00001800UL /* Previously Machine mode */ +#define SR_SUM 0x00040000UL /* Supervisor User Memory Access */ + +#define SR_FS 0x00006000UL /* Floating-point Status */ +#define SR_FS_OFF 0x00000000UL +#define SR_FS_INITIAL 0x00002000UL +#define SR_FS_CLEAN 0x00004000UL +#define SR_FS_DIRTY 0x00006000UL + +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV || CONFIG_CPU_XUANTIE_R920 +#define SR_VS 0x01800000 +#define SR_VS_OFF 0x00000000 +#define SR_VS_INITIAL 0x00800000 +#define SR_VS_CLEAN 0x01000000 +#define SR_VS_DIRTY 0x01800000 +#else +#define SR_VS 0x00000600 +#define SR_VS_OFF 0x00000000 +#define SR_VS_INITIAL 0x00000200 +#define SR_VS_CLEAN 0x00000400 +#define SR_VS_DIRTY 0x00000600 +#endif + +#if __riscv_matrix || __riscv_xtheadmatrix +#define SR_MS 0x06000000 +#define SR_MS_OFF 0x00000000 +#define SR_MS_INITIAL 0x02000000 +#define SR_MS_CLEAN 0x04000000 +#define SR_MS_DIRTY 0x06000000 +#endif + +/* Interrupt-enable Registers */ +#define IE_MTIE 0x00000080UL +#define IE_MEIE 0x00000800UL + +/* ===== Trap/Exception Causes ===== */ +#define CAUSE_MISALIGNED_FETCH 0x0 +#define CAUSE_FETCH_ACCESS 0x1 +#define CAUSE_ILLEGAL_INSTRUCTION 0x2 +#define CAUSE_BREAKPOINT 0x3 +#define CAUSE_MISALIGNED_LOAD 0x4 +#define CAUSE_LOAD_ACCESS 0x5 +#define CAUSE_MISALIGNED_STORE 0x6 +#define CAUSE_STORE_ACCESS 0x7 +#define CAUSE_USER_ECALL 0x8 +#define CAUSE_SUPERVISOR_ECALL 0x9 +#define CAUSE_VIRTUAL_SUPERVISOR_ECALL 0xa +#define CAUSE_MACHINE_ECALL 0xb +#define CAUSE_FETCH_PAGE_FAULT 0xc +#define CAUSE_LOAD_PAGE_FAULT 0xd +#define CAUSE_STORE_PAGE_FAULT 0xf + +#define PRV_U 0 +#define PRV_S 1 +#define PRV_M 3 + + +#define MSTATUS_SIE 0x00000002 +#define MSTATUS_MIE 0x00000008 +#define MSTATUS_SPIE_SHIFT 5 +#define MSTATUS_SPIE (1 << MSTATUS_SPIE_SHIFT) +#define MSTATUS_UBE 0x00000040 +#define MSTATUS_MPIE 0x00000080 +#define MSTATUS_SPP_SHIFT 8 +#define MSTATUS_SPP (1 << MSTATUS_SPP_SHIFT) +#define MSTATUS_MPP_SHIFT 11 +#define MSTATUS_MPP (3 << MSTATUS_MPP_SHIFT) + +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 +#define MSTATUS_VS_SHIFT 23 +#else +#define MSTATUS_VS_SHIFT 9 +#endif +#define MSTATUS_FS_SHIFT 13 +#define MSTATUS_MS_SHIFT 25 + +#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) + +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V ||CONFIG_CPU_XUANTIE_C908I || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 +#define ATTR_SO (1ull << 4) +#define ATTR_CA (1ull << 3) +#define ATTR_BU (1ull << 2) +#define ATTR_SH (1ull << 1) +#define ATTR_SE (1ull << 0) + +#define UPPER_ATTRS_SHIFT (59) +#define UPPER_ATTRS(x) (((x) & 0x1f) << UPPER_ATTRS_SHIFT) +#else +#if __riscv_xlen == 32 +#define PTE_PBMT_SHIFT (30) +#else +#define PTE_PBMT_SHIFT (61) +#endif /* end __riscv_xlen */ +#define SVPBMT_PMA ((unsigned long)0x0 << PTE_PBMT_SHIFT) +#define SVPBMT_NC ((unsigned long)0x1 << PTE_PBMT_SHIFT) +#define SVPBMT_IO ((unsigned long)0x2 << PTE_PBMT_SHIFT) +#define SVPBMT_MASK ((unsigned long)0x3 << PTE_PBMT_SHIFT) + +#endif + +#define DIRTY_FLAG (1 << 6) +#define ACCESS_FLAG (1 << 5) +#define GLOBAL_FLAG (1 << 4) +#define AP_UNPRIV (1 << 3) +#define AP_X (1 << 2) +#define AP_W (1 << 1) +#define AP_R (1 << 0) + +#define LOWER_ATTRS_SHIFT 1 +#define LOWER_ATTRS(x) (((x) & 0x1ff) << LOWER_ATTRS_SHIFT) + + + +#endif /* __RISCV_CSR_H__ */ + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/csi_config.h b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/csi_config.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/drv/dev_tag.h b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/drv/dev_tag.h new file mode 100644 index 00000000000..80150c85cd8 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/drv/dev_tag.h @@ -0,0 +1,102 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/dev_tag.h + * @brief Header File for DEV TAG Driver + * @version V1.0 + * @date 31. March 2020 + * @model common + ******************************************************************************/ + +#ifndef _DRV_DEV_TAG_H_ +#define _DRV_DEV_TAG_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + DEV_BLANK_TAG = 0U, + DEV_DW_UART_TAG, + DEV_DW_DMA_TAG, + DEV_DW_GPIO_TAG, + DEV_DW_IIC_TAG, + DEV_DW_QSPI_TAG, + DEV_DW_SDMMC_TAG, + DEV_DW_SDHCI_TAG, + DEV_DW_SPI_TAG, + DEV_DW_TIMER_TAG, + DEV_DW_WDT_TAG, + DEV_WJ_ADC_TAG, + DEV_WJ_AES_TAG, + DEV_WJ_CODEC_TAG, + DEV_WJ_CRC_TAG, + DEV_WJ_DMA_TAG, + DEV_WJ_EFLASH_TAG, + DEV_WJ_EFUSE_TAG, + DEV_WJ_ETB_TAG, + DEV_WJ_FFT_TAG, + DEV_WJ_I2S_TAG, + DEV_WJ_MBOX_TAG, + DEV_WJ_PADREG_TAG, + DEV_WJ_PDM_TAG, + DEV_WJ_PINMUX_TAG, + DEV_WJ_PMU_TAG, + DEV_WJ_PWM_TAG, + DEV_WJ_RNG_TAG, + DEV_WJ_ROM_TAG, + DEV_WJ_RSA_TAG, + DEV_WJ_RTC_TAG, + DEV_WJ_SASC_TAG, + DEV_WJ_SHA_TAG, + DEV_WJ_SPDIF_TAG, + DEV_WJ_SPIDF_TAG, + DEV_WJ_TDM_TAG, + DEV_WJ_TIPC_TAG, + DEV_WJ_USB_TAG, + DEV_WJ_USI_TAG, + DEV_WJ_VAD_TAG, + DEV_CD_QSPI_TAG, + DEV_DCD_ISO7816_TAG, + DEV_OSR_RNG_TAG, + DEV_QX_RTC_TAG, + DEV_RCHBAND_CODEC_TAG, + DEV_CMSDK_UART_TAG, + DEV_RAMBUS_150B_PKA_TAG, + DEV_RAMBUS_150B_TRNG_TAG, + DEV_RAMBUS_120SI_TAG, + DEV_RAMBUS_120SII_TAG, + DEV_RAMBUS_120SIII_TAG, + DEV_WJ_AVFS_TAG, + DEV_WJ_BMU_TAG, +} csi_dev_tag_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_TAG_H_ */ + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/dw_timer_ll.h b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/dw_timer_ll.h new file mode 100644 index 00000000000..c2289d97706 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/dw_timer_ll.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + */ + +/******************************************************* + * @file dw_timer_ll.h + * @brief header file for timer ll driver + * @version V1.0 + * @date 9. April 2020 + * ******************************************************/ + +#ifndef _DW_TIMER_LL_H_ +#define _DW_TIMER_LL_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! Timer1 Control Reg, offset: 0x08 */ +#define DW_TIMER_CTL_ENABLE_SEL_Pos (0U) +#define DW_TIMER_CTL_ENABLE_SEL_Msk (0x1U << DW_TIMER_CTL_ENABLE_SEL_Pos) +#define DW_TIMER_CTL_ENABLE_SEL_EN DW_TIMER_CTL_ENABLE_SEL_Msk + +#define DW_TIMER_CTL_MODE_SEL_Pos (1U) +#define DW_TIMER_CTL_MODE_SEL_Msk (0x1U << DW_TIMER_CTL_MODE_SEL_Pos) +#define DW_TIMER_CTL_MODE_SEL_EN DW_TIMER_CTL_MODE_SEL_Msk + +#define DW_TIMER_CTL_INT_MASK_Pos (2U) +#define DW_TIMER_CTL_INT_MASK_Msk (0x1U << DW_TIMER_CTL_INT_MASK_Pos) +#define DW_TIMER_CTL_INT_MAKS_EN DW_TIMER_CTL_INT_MASK_Msk + +#define DW_TIMER_CTL_HARD_TRIG_Pos (4U) +#define DW_TIMER_CTL_HARD_TRIG_Msk (0x1U << DW_TIMER_CTL_HARD_TRIG_Pos) +#define DW_TIMER_CTL_HARD_TRIG_EN DW_TIMER_CTL_HARD_TRIG_Msk + +/*! Timer EOI, offset: 0x0c */ +#define DW_TIMER_EOI_REG_Pos (0U) +#define DW_TIMER_EOI_REG_Msk (0x1U << DW_TIMER_EOI_REG_Pos) +#define DW_TIMER_EOI_REG_EN DW_TIMER_EOI_REG_Msk + +/*! Timer Int Status, offset: 0x10 */ +#define DW_TIMER_INT_STATUS_Pos (0U) +#define DW_TIMER_INT_STATUS_Msk (0x1U << DW_TIMER_INT_STATUS_Pos) +#define DW_TIMER_INT_STATUS_EN DW_TIMER_INT_STATUS_Msk + +/*! Timers Int Status, offset: 0xa0 */ +#define DW_TIMERS_INT_STATUS_Pos (0U) +#define DW_TIMERS_INT_STATUS_Msk (0x2U << DW_TIMERS_INT_STATUS_Pos) +#define DW_TIMERS_INT_STATUS_EN DW_TIMERS_INT_STATUS_Msk + +/*! Timers EOI, offset: 0xa4 */ +#define DW_TIMERS_EOI_REG_Pos (0U) +#define DW_TIMERS_EOI_REG_Msk (0x2U << DW_TIMERS_EOI_REG_Pos) +#define DW_TIMERS_EOI_REG_EN DW_TIMERS_EOI_REG_Msk + +/*! Timers Raw Int Status,offset: 0xa8 */ +#define DW_TIMERS_RAW_INT_STA_Pos (0U) +#define DW_TIMERS_RAW_INT_STA_Msk (0x2U << DW_TIMERS_RAW_INT_STA_Pos) +#define DW_TIMERS_RAW_INT_STA_EN DW_TIMERS_RAW_INT_STA_Msk + +typedef struct { + __IOM uint32_t TLC; /* Offset: 0x000 (R/W) TimerLoadCount */ + __IM uint32_t TCV; /* Offset: 0x004 (R/ ) TimerCurrentValue */ + __IOM uint32_t TCR; /* Offset: 0x008 (R/W) TimerControlReg */ + __IM uint32_t TEOI; /* Offset: 0x00c (R/ ) TimerEOI */ + __IM uint32_t TIS; /* Offset: 0x010 (R/ ) TimerIntStatus */ +} dw_timer_regs_t; + +typedef struct { + dw_timer_regs_t timer[8]; + __IM uint32_t TSIS; /* Offset: 0x0a0 (R/ ) TimersIntStatus */ + __IM uint32_t TSEOI; /* Offset: 0x0a4 (R/ ) TimersEOI */ + __IM uint32_t TSRIS; /* Offset: 0x0a8 (R/ ) TimersRawIntStatus */ +} dw_timer_general_regs_t; + +static inline uint32_t dw_timer_read_load(dw_timer_regs_t *timer_base) +{ + return (timer_base->TLC); +} +static inline void dw_timer_write_load(dw_timer_regs_t *timer_base, uint32_t value) +{ + timer_base->TLC = value; +} +static inline uint32_t dw_timer_get_current(dw_timer_regs_t *timer_base) +{ + return (timer_base->TCV); +} +static inline void dw_timer_set_enable(dw_timer_regs_t *timer_base) +{ + timer_base->TCR |= (DW_TIMER_CTL_ENABLE_SEL_EN); +} +static inline void dw_timer_set_disable(dw_timer_regs_t *timer_base) +{ + timer_base->TCR &= ~(DW_TIMER_CTL_ENABLE_SEL_EN); +} +static inline uint32_t dw_timer_get_enable(dw_timer_regs_t *timer_base) +{ + return (((timer_base->TCR) & DW_TIMER_CTL_ENABLE_SEL_EN) ? (uint32_t)1 : (uint32_t)0); +} +static inline void dw_timer_set_mode_free(dw_timer_regs_t *timer_base) +{ + timer_base->TCR &= ~(DW_TIMER_CTL_MODE_SEL_EN); +} +static inline void dw_timer_set_mode_load(dw_timer_regs_t *timer_base) +{ + timer_base->TCR |= (DW_TIMER_CTL_MODE_SEL_EN); +} +static inline uint32_t dw_timer_get_model(dw_timer_regs_t *timer_base) +{ + return (((timer_base->TCR) & DW_TIMER_CTL_MODE_SEL_EN) ? (uint32_t)1 : (uint32_t)0); +} +static inline void dw_timer_set_mask(dw_timer_regs_t *timer_base) +{ + timer_base->TCR |= (DW_TIMER_CTL_INT_MAKS_EN); +} +static inline void dw_timer_set_unmask(dw_timer_regs_t *timer_base) +{ + timer_base->TCR &= ~(DW_TIMER_CTL_INT_MAKS_EN); +} +static inline uint32_t dw_timer_get_mask(dw_timer_regs_t *timer_base) +{ + return (((timer_base->TCR) & DW_TIMER_CTL_INT_MAKS_EN) ? (uint32_t)1 : (uint32_t)0); +} +static inline void dw_timer_set_hardtrigger_en(dw_timer_regs_t *timer_base) +{ + timer_base->TCR |= (DW_TIMER_CTL_HARD_TRIG_EN); +} +static inline void dw_timer_set_hardtrigger_dis(dw_timer_regs_t *timer_base) +{ + timer_base->TCR &= ~(DW_TIMER_CTL_HARD_TRIG_EN); +} +static inline uint32_t dw_timer_get_hardtrigger(dw_timer_regs_t *timer_base) +{ + return (((timer_base->TCR) & DW_TIMER_CTL_HARD_TRIG_EN) ? (uint32_t)1 : (uint32_t)0); +} +static inline uint32_t dw_timer_clear_irq(dw_timer_regs_t *timer_base) +{ + return (((timer_base->TEOI) & DW_TIMER_EOI_REG_EN) ? (uint32_t)1 : (uint32_t)0); +} +static inline uint32_t dw_timer_get_int_status(dw_timer_regs_t *timer_base) +{ + return (((timer_base->TIS) & DW_TIMER_INT_STATUS_EN) ? (uint32_t)1 : (uint32_t)0); +} +static inline uint32_t dw_timer_general_active_after_mask(dw_timer_general_regs_t *timer_base) +{ + return ((timer_base->TSIS) & DW_TIMERS_INT_STATUS_EN); +} +static inline uint32_t dw_timer_general_clear_irq(dw_timer_general_regs_t *timer_base) +{ + return ((timer_base->TSEOI) & DW_TIMERS_EOI_REG_EN); +} +static inline uint32_t dw_timer_general_active_prior_mask(dw_timer_general_regs_t *timer_base) +{ + return ((timer_base->TSRIS) & DW_TIMERS_RAW_INT_STA_EN); +} + + +#ifdef __cplusplus +} +#endif + +#endif /* _DW_TIMER_LL_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/dw_uart.h b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/dw_uart.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/dw_uart_ll.h b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/dw_uart_ll.h new file mode 100644 index 00000000000..9f79cb80812 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/dw_uart_ll.h @@ -0,0 +1,429 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file dw_uart_ll.h + * @brief header file for uart ll driver + * @version V1.0 + * @date 18. December 2024 + ******************************************************************************/ + +#ifndef _DW_UART_LL_H_ +#define _DW_UART_LL_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_XIP +#define ATTRIBUTE_DATA __attribute__((section(".ram.code"))) +#else +#define ATTRIBUTE_DATA +#endif + +/*! IER, offset: 0x4 */ +#define DW_UART_IER_ERBFI_Pos (0U) +#define DW_UART_IER_ERBFI_Msk (0x1U << DW_UART_IER_ERBFI_Pos) +#define DW_UART_IER_ERBFI_EN DW_UART_IER_ERBFI_Msk + +#define DW_UART_IER_ETBEI_Pos (1U) +#define DW_UART_IER_ETBEI_Msk (0x1U << DW_UART_IER_ETBEI_Pos) +#define DW_UART_IER_ETBEI_EN DW_UART_IER_ETBEI_Msk + +#define DW_UART_IER_ELSI_Pos (2U) +#define DW_UART_IER_ELSI_Msk (0x1U << DW_UART_IER_ELSI_Pos) +#define DW_UART_IER_ELSI_EN DW_UART_IER_ELSI_Msk + +#define DW_UART_IER_EDSSI_Pos (3U) +#define DW_UART_IER_EDSSI_Msk (0x1U << DW_UART_IER_EDSSI_Pos) +#define DW_UART_IER_EDSSI_EN DW_UART_IER_EDSSI_Msk + +/*! IIR, offset: 0x8 */ +#define DW_UART_IIR_IID_Pos (0U) +#define DW_UART_IIR_IID_Msk (0xFU << DW_UART_IIR_IID_Pos) +#define DW_UART_IIR_IID_MODEM_STATUS (0x0U) +#define DW_UART_IIR_IID_NO_INTERRUPT (0x1U) +#define DW_UART_IIR_IID_THR_EMPTY (0x2U) +#define DW_UART_IIR_IID_RECV_DATA_AVAIL (0x4U) +#define DW_UART_IIR_IID_RECV_LINE_STATUS (0x6U) +#define DW_UART_IIR_IID_BUSY_DETECT (0x7U) +#define DW_UART_IIR_IID_CHARACTER_TIMEOUT (0xCU) + +#define DW_UART_IIR_FIFOSE_Pos (6U) +#define DW_UART_IIR_FIFOSE_Msk (0x3U << DW_UART_IIR_FIFOSE_Pos) +#define DW_UART_IIR_FIFOSE_EN DW_UART_IIR_FIFOSE_Msk + +/*! FCR, offset: 0x8 */ +#define DW_UART_FCR_FIFOE_Pos (0U) +#define DW_UART_FCR_FIFOE_Msk (0x1U << DW_UART_FCR_FIFOE_Pos) +#define DW_UART_FCR_FIFOE_EN DW_UART_FCR_FIFOE_Msk + +#define DW_UART_FCR_RFIFOR_Pos (1U) +#define DW_UART_FCR_RFIFOR_Msk (0x1U << DW_UART_FCR_RFIFOR_Pos) +#define DW_UART_FCR_RFIFOR_RESET DW_UART_FCR_RFIFOR_Msk + +#define DW_UART_FCR_XFIFOR_Pos (2U) +#define DW_UART_FCR_XFIFOR_Msk (0x1U << DW_UART_FCR_XFIFOR_Pos) +#define DW_UART_FCR_XFIFOR_RESET DW_UART_FCR_XFIFOR_Msk + +#define DW_UART_FCR_TET_Pos (4U) +#define DW_UART_FCR_TET_Msk (0x3U << DW_UART_FCR_TET_Pos) +#define DW_UART_FCR_TET_FIFO_EMTPY (0x0U) +#define DW_UART_FCR_TET_FIFO_2_CHAR (0x1U << DW_UART_FCR_TET_Pos) +#define DW_UART_FCR_TET_FIFO_1_4_FULL (0x2U << DW_UART_FCR_TET_Pos) +#define DW_UART_FCR_TET_FIFO_1_2_FULL (0x3U << DW_UART_FCR_TET_Pos) + +#define DW_UART_FCR_RT_Pos (6U) +#define DW_UART_FCR_RT_Msk (0x3U << DW_UART_FCR_RT_Pos) +#define DW_UART_FCR_RT_FIFO_1_CHAR (0x0U) +#define DW_UART_FCR_RT_FIFO_1_4_FULL (0x1U << DW_UART_FCR_RT_Pos) +#define DW_UART_FCR_RT_FIFO_1_2_FULL (0x2U << DW_UART_FCR_RT_Pos) +#define DW_UART_FCR_RT_FIFO_2_LESS_FULL (0x3U << DW_UART_FCR_RT_Pos) + +/*! LCR, offset: 0xC */ +#define DW_UART_LCR_DLS_Pos (0U) +#define DW_UART_LCR_DLS_Msk (0x3U << DW_UART_LCR_DLS_Pos) +#define DW_UART_LCR_DLS_5_BITS (0x0U) +#define DW_UART_LCR_DLS_6_BITS (0x1U << DW_UART_LCR_DLS_Pos) +#define DW_UART_LCR_DLS_7_BITS (0x2U << DW_UART_LCR_DLS_Pos) +#define DW_UART_LCR_DLS_8_BITS (0x3U << DW_UART_LCR_DLS_Pos) + +#define DW_UART_LCR_STOP_Pos (2U) +#define DW_UART_LCR_STOP_Msk (0x1U << DW_UART_LCR_STOP_Pos) +#define DW_UART_LCR_STOP_1_BIT (0x0U) +#define DW_UART_LCR_STOP_2_BIT (0x1U << DW_UART_LCR_STOP_Pos) + +#define DW_UART_LCR_PEN_Pos (3U) +#define DW_UART_LCR_PEN_Msk (0x1U << DW_UART_LCR_PEN_Pos) +#define DW_UART_LCR_PEN_EN DW_UART_LCR_PEN_Msk + +#define DW_UART_LCR_EPS_Pos (4U) +#define DW_UART_LCR_EPS_Msk (0x1U << DW_UART_LCR_EPS_Pos) +#define DW_UART_LCR_EPS_EN DW_UART_LCR_EPS_Msk + +#define DW_UART_LCR_BC_Pos (6U) +#define DW_UART_LCR_BC_Msk (0x1U << DW_UART_LCR_BC_Pos) +#define DW_UART_LCR_BC_EN DW_UART_LCR_BC_Msk + +#define DW_UART_LCR_DLAB_Pos (7U) +#define DW_UART_LCR_DLAB_Msk (0x1U << DW_UART_LCR_DLAB_Pos) +#define DW_UART_LCR_DLAB_EN DW_UART_LCR_DLAB_Msk + +/*! MCR, offset: 0x10 */ +#define DW_UART_MCR_RTS_Pos (1U) +#define DW_UART_MCR_RTS_Msk (0x1U << DW_UART_MCR_RTS_Pos) +#define DW_UART_MCR_RTS_EN DW_UART_MCR_RTS_Msk + +#define DW_UART_MCR_LB_Pos (4U) +#define DW_UART_MCR_LB_Msk (0x1U << DW_UART_MCR_LB_Pos) +#define DW_UART_MCR_LB_EN DW_UART_MCR_LB_Msk + +#define DW_UART_MCR_AFCE_Pos (5U) +#define DW_UART_MCR_AFCE_Msk (0x1U << DW_UART_MCR_AFCE_Pos) +#define DW_UART_MCR_AFCE_EN DW_UART_MCR_AFCE_Msk + +/*! LSR, offset: 0x14 */ +#define DW_UART_LSR_DR_Pos (0U) +#define DW_UART_LSR_DR_Msk (0x1U << DW_UART_LSR_DR_Pos) +#define DW_UART_LSR_DR_READY DW_UART_LSR_DR_Msk + +#define DW_UART_LSR_OE_Pos (1U) +#define DW_UART_LSR_OE_Msk (0x1U << DW_UART_LSR_OE_Pos) +#define DW_UART_LSR_OE_ERROR DW_UART_LSR_OE_Msk + +#define DW_UART_LSR_PE_Pos (2U) +#define DW_UART_LSR_PE_Msk (0x1U << DW_UART_LSR_PE_Pos) +#define DW_UART_LSR_PE_ERROR DW_UART_LSR_PE_Msk + +#define DW_UART_LSR_FE_Pos (3U) +#define DW_UART_LSR_FE_Msk (0x1U << DW_UART_LSR_FE_Pos) +#define DW_UART_LSR_FE_ERROR DW_UART_LSR_FE_Msk + +#define DW_UART_LSR_BI_Pos (4U) +#define DW_UART_LSR_BI_Msk (0x1U << DW_UART_LSR_BI_Pos) +#define DW_UART_LSR_BI_SET DW_UART_LSR_BI_Msk + +#define DW_UART_LSR_THRE_Pos (5U) +#define DW_UART_LSR_THRE_Msk (0x1U << DW_UART_LSR_THRE_Pos) +#define DW_UART_LSR_THRE_SET DW_UART_LSR_THRE_Msk + +#define DW_UART_LSR_TEMT_Pos (6U) +#define DW_UART_LSR_TEMT_Msk (0x1U << DW_UART_LSR_TEMT_Pos) +#define DW_UART_LSR_TEMT_SET DW_UART_LSR_TEMT_Msk + +#define DW_UART_LSR_RFE_Pos (7U) +#define DW_UART_LSR_RFE_Msk (0x1U << DW_UART_LSR_RFE_Pos) +#define DW_UART_LSR_RFE_ERROR DW_UART_LSR_RFE_Msk + +/*! MSR, offset: 0x18 */ +#define DW_UART_MSR_DCTS_Pos (0U) +#define DW_UART_MSR_DCTS_Msk (0x1U << DW_UART_MSR_DCTS_Pos) +#define DW_UART_MSR_DCTS_CHANGE DW_UART_MSR_DCTS_Msk + +#define DW_UART_MSR_DDSR_Pos (1U) +#define DW_UART_MSR_DDSR_Msk (0x1U << DW_UART_MSR_DDSR_Pos) +#define DW_UART_MSR_DDSR_CHANGE DW_UART_MSR_DDSR_Msk + +#define DW_UART_MSR_TERI_Pos (2U) +#define DW_UART_MSR_TERI_Msk (0x1U << DW_UART_MSR_TERI_Pos) +#define DW_UART_MSR_TERI_CHANGE DW_UART_MSR_TERI_Msk + +#define DW_UART_MSR_DDCD_Pos (3U) +#define DW_UART_MSR_DDCD_Msk (0x1U << DW_UART_MSR_DDCD_Pos) +#define DW_UART_MSR_DDCD_CHANGE DW_UART_MSR_DDCD_Msk + +#define DW_UART_MSR_CTS_Pos (4U) +#define DW_UART_MSR_CTS_Msk (0x1U << DW_UART_MSR_CTS_Pos) +#define DW_UART_MSR_CTS_ASSERTED DW_UART_MSR_CTS_Msk + +#define DW_UART_MSR_DSR_Pos (5U) +#define DW_UART_MSR_DSR_Msk (0x1U << DW_UART_MSR_DSR_Pos) +#define DW_UART_MSR_DSR_ASSERTED DW_UART_MSR_DSR_Msk + +#define DW_UART_MSR_RI_Pos (6U) +#define DW_UART_MSR_RI_Msk (0x1U << DW_UART_MSR_RI_Pos) +#define DW_UART_MSR_RI_ASSERTED DW_UART_MSR_RI_Msk + +#define DW_UART_MSR_DCD_Pos (7U) +#define DW_UART_MSR_DCD_Msk (0x1U << DW_UART_MSR_DCD_Pos) +#define DW_UART_MSR_DCD_ASSERTED DW_UART_MSR_DCD_Msk + +/*! SCR, offset: 0x1C */ +#define DW_UART_SCR_SCRATCHPAD_Pos (0U) +#define DW_UART_SCR_SCRATCHPAD_Msk (0xFFU << DW_UART_SCR_SCRATCHPAD_Pos) + +/*! USR, offset: 0x7C */ +#define DW_UART_USR_BUSY_Pos (0U) +#define DW_UART_USR_BUSY_Msk (0x1U << DW_UART_USR_BUSY_Pos) +#define DW_UART_USR_BUSY_SET DW_UART_USR_BUSY_Msk + +#define DW_UART_USR_TFNF_Pos (1U) +#define DW_UART_USR_TFNF_Msk (0x1U << DW_UART_USR_TFNF_Pos) +#define DW_UART_USR_TFNF_SET DW_UART_USR_TFNF_Msk + +#define DW_UART_USR_TFE_Pos (2U) +#define DW_UART_USR_TFE_Msk (0x1U << DW_UART_USR_TFE_Pos) +#define DW_UART_USR_TFE_SET DW_UART_USR_TFE_Msk + +#define DW_UART_USR_RFNE_Pos (3U) +#define DW_UART_USR_RFNE_Msk (0x1U << DW_UART_USR_RFNE_Pos) +#define DW_UART_USR_RFNE_SET DW_UART_USR_RFNE_Msk + +#define DW_UART_USR_RFF_Pos (4U) +#define DW_UART_USR_RFF_Msk (0x1U << DW_UART_USR_RFF_Pos) +#define DW_UART_USR_RFF_SET DW_UART_USR_RFF_Msk + +/*! TFL, offset: 0x80 */ +#define DW_UART_TFL_TFIFOL_Pos (0U) +#define DW_UART_TFL_TFIFOL_Msk (0x1FU << DW_UART_TFL_TFIFOL_Pos) +#define DW_UART_TFL_TFIFOL(n) (nU << DW_UART_TFL_TFIFOL_Pos) + +/*! RFL, offset: 0x84 */ +#define DW_UART_RFL_RFIFOL_Pos (0U) +#define DW_UART_RFL_RFIFOL_Msk (0x1FU << DW_UART_RFL_RFIFOL_Pos) +#define DW_UART_RFL_RFIFOL(n) (nU << DW_UART_TFL_TFIFOL_Pos) + +/*! HTX, offset: 0xA4 */ +#define DW_UART_HTX_HALTTX_Pos (0U) +#define DW_UART_HTX_HALTTX_Msk (0x1U << DW_UART_HTX_HALTTX_Pos) +#define DW_UART_HTX_HALTTX_EN DW_UART_HTX_HALTTX_Msk + +#define DW_UART_HTX_RX_ETB_FUNC_Pos (6U) +#define DW_UART_HTX_RX_ETB_FUNC_Msk (0x1U << DW_UART_HTX_RX_ETB_FUNC_Pos) +#define DW_UART_HTX_RX_ETB_FUNC_EN DW_UART_HTX_RX_ETB_FUNC_Msk + +#define DW_UART_HTX_TX_ETB_FUNC_Pos (7U) +#define DW_UART_HTX_TX_ETB_FUNC_Msk (0x1U << DW_UART_HTX_TX_ETB_FUNC_Pos) +#define DW_UART_HTX_TX_ETB_FUNC_EN DW_UART_HTX_TX_ETB_FUNC_Msk + +/*! DMASA, offset: 0xA8 */ +#define DW_UART_DMASA_DMASACK_Pos (0U) +#define DW_UART_DMASA_DMASACK_Msk (0x1U << DW_UART_DMASA_DMASACK_Pos) +#define DW_UART_DMASA_DMASACK_SET DW_UART_DMASA_DMASACK_Msk + +/* FIFO CONFIG */ +#define UART_FIFO_INIT_CONFIG (DW_UART_FCR_FIFOE_EN | DW_UART_FCR_RT_FIFO_1_2_FULL|DW_UART_FCR_RFIFOR_RESET|DW_UART_FCR_XFIFOR_RESET) + +/*! UART_RATE, offset: 0x3FC */ +#define DW_UART_SUPPORT_RATE 0x10102U + +#define UART_BUSY_TIMEOUT 0x70000000U + +typedef struct { + union { + __IM uint32_t RBR; /* Offset: 0x000 (R/ ) Receive buffer register */ + __OM uint32_t THR; /* Offset: 0x000 ( /W) Transmission hold register */ + __IOM uint32_t DLL; /* Offset: 0x000 (R/W) Clock frequency division low section register */ + }; + union { + __IOM uint32_t DLH; /* Offset: 0x004 (R/W) Clock frequency division high section register */ + __IOM uint32_t IER; /* Offset: 0x004 (R/W) Interrupt enable register */ + }; + union { + __IM uint32_t IIR; /* Offset: 0x008 (R/ ) Interrupt identification register */ + __OM uint32_t FCR; /* Offset: 0x008 ( /W) FIFO control register */ + }; + __IOM uint32_t LCR; /* Offset: 0x00C (R/W) Line control register */ + __IOM uint32_t MCR; /* Offset: 0x010 (R/W) Modem control register */ + __IM uint32_t LSR; /* Offset: 0x014 (R/ ) Line state register */ + __IM uint32_t MSR; /* Offset: 0x018 (R/ ) Modem state register */ + uint32_t RESERVED1[21]; + __IM uint32_t USR; /* Offset: 0x07c (R/ ) UART state register */ +} dw_uart_regs_t; + +static inline void dw_uart_enable_recv_irq(dw_uart_regs_t *uart_base) +{ + uart_base->IER |= (DW_UART_IER_ERBFI_EN | DW_UART_IER_ELSI_EN); +} + +static inline void dw_uart_disable_recv_irq(dw_uart_regs_t *uart_base) +{ + uart_base->IER &= ~(DW_UART_IER_ERBFI_EN | DW_UART_IER_ELSI_EN); +} + +static inline void dw_uart_enable_trans_irq(dw_uart_regs_t *uart_base) +{ + uart_base->IER |= DW_UART_IER_ETBEI_EN; +} + +static inline void dw_uart_disable_trans_irq(dw_uart_regs_t *uart_base) +{ + uart_base->IER &= ~(DW_UART_IER_ETBEI_EN); +} + +static inline void dw_uart_fifo_init(dw_uart_regs_t *uart_base) +{ + /* FIFO enable */ + uart_base->FCR = UART_FIFO_INIT_CONFIG; +} + +static inline void dw_uart_fifo_enable(dw_uart_regs_t *uart_base) +{ + uart_base->FCR |= DW_UART_FCR_FIFOE_EN; +} + +static inline void dw_uart_fifo_disable(dw_uart_regs_t *uart_base) +{ + uart_base->FCR &= ~(DW_UART_FCR_FIFOE_EN); +} + +static inline uint32_t dw_uart_putready(dw_uart_regs_t *uart_base) +{ + uint32_t status = 0U, ret = 0U; + + status = uart_base->LSR & DW_UART_LSR_THRE_SET; + + if (status != 0U) { + ret = 1U; + } + + return ret; +} + +static inline uint32_t dw_uart_getready(dw_uart_regs_t *uart_base) +{ + uint32_t status = 0U, ret = 0U; + + status = uart_base->LSR & DW_UART_LSR_DR_READY; + + if (status != 0U) { + ret = 1U; + } + + return ret; +} + +static inline uint32_t dw_uart_get_line_status(dw_uart_regs_t *uart_base) +{ + return uart_base->LSR; +} + +static inline void dw_uart_config_stop_bits_1(dw_uart_regs_t *uart_base) +{ + uart_base->LCR &= ~(DW_UART_LCR_STOP_Msk); +} + +static inline void dw_uart_config_stop_bits_2(dw_uart_regs_t *uart_base) +{ + uart_base->LCR |= DW_UART_LCR_STOP_2_BIT; +} + +static inline void dw_uart_putchar(dw_uart_regs_t *uart_base, uint8_t ch) +{ + uart_base->THR = ch; +} + +static inline uint8_t dw_uart_getchar(dw_uart_regs_t *uart_base) +{ + return (uint8_t)(uart_base->RBR); +} + +static inline uint32_t dw_uart_get_intr_en_status(dw_uart_regs_t *uart_base) +{ + return uart_base->IER; +} + +static inline void dw_uart_set_intr_en_status(dw_uart_regs_t *uart_base, uint32_t status) +{ + uart_base->IER = status; +} + +static inline void dw_uart_set_fcr_reg(dw_uart_regs_t *uart_base, uint32_t value) +{ + uart_base->FCR = value; +} + +static inline void dw_uart_enable_auto_flow_control(dw_uart_regs_t *uart_base) +{ + uart_base->MCR |= DW_UART_MCR_AFCE_EN; + uart_base->MCR |= DW_UART_MCR_RTS_EN; +} + +static inline void dw_uart_disable_auto_flow_control(dw_uart_regs_t *uart_base) +{ + uart_base->MCR &= ~DW_UART_MCR_AFCE_EN; + uart_base->MCR &= ~DW_UART_MCR_RTS_EN; +} + +int32_t dw_uart_wait_timeout(dw_uart_regs_t *uart_base); + +int32_t dw_uart_wait_idle(dw_uart_regs_t *uart_base); + +int32_t dw_uart_config_baudrate(dw_uart_regs_t *uart_base, uint32_t baud, uint32_t uart_freq); + +int32_t dw_uart_config_stop_bits(dw_uart_regs_t *uart_base, uint32_t stop_bits); + +int32_t dw_uart_config_parity_none(dw_uart_regs_t *uart_base); + +int32_t dw_uart_config_parity_odd(dw_uart_regs_t *uart_base); + +int32_t dw_uart_config_parity_even(dw_uart_regs_t *uart_base); + +int32_t dw_uart_config_data_bits(dw_uart_regs_t *uart_base, uint32_t data_bits); + +#ifdef __cplusplus +} +#endif + +#endif /* _DW_UART_LL_H_ */ + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/soc.h b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/soc.h new file mode 100644 index 00000000000..26a29b0e09b --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/soc.h @@ -0,0 +1,322 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 _SOC_H_ +#define _SOC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef EHS_VALUE +#define EHS_VALUE 20000000U +#endif + +#ifndef ELS_VALUE +#define ELS_VALUE 32768U +#endif + +#ifndef IHS_VALUE +#define IHS_VALUE 20000000U +#endif + +#ifndef ILS_VALUE +#define ILS_VALUE 32768U +#endif + +typedef enum { + DW_UART0_RX_DMAN = 0U, + DW_UART0_TX_DMAN = 1U, + DW_UART1_RX_DMAN = 2U, + DW_UART1_TX_DMAN = 3U, + MEMORY_DMAN = 4U, +} dman_type_t; + +typedef enum { + PA0 = 0U, + PA1, + PA2, + PA3, + PA4, + PA5, + PA6, + PA7, + PA8, + PA9, + PA10, + PA11, + PA12, + PA13, + PA14, + PA15, + PA16, + PA17, + PA18, + PA19, + PA20, + PA21, + PA22, + PA23, + PA24, + PA25, + PA26, + PA27, + PA28, + PA29, + PA30, + PA31, + PIN_END = 0xFFFFFFFFU +} pin_name_t; + + +typedef enum { + PA0_I2S0_SCLK = 0U, + PA0_SPI0_CS = 1U, + PA0_UART0_RX = 2U, + PA0_PWM_CH0 = 3U, + PA1_I2S0_WSCLK = 0U, + PA1_SPI0_SCK = 1U, + PA1_UART0_TX = 2U, + PA1_PWM_CH1 = 3U, + PA2_I2S1_SCLK = 0U, + PA2_IIC0_SCL = 1U, + PA2_SPI1_CS = 2U, + PA2_PWM_CH2 = 3U, + PA2_ADC_A0 = 7U, + PA3_I2S1_WSCLK = 0U, + PA3_IIC0_SDA = 1U, + PA3_SPI1_SCK = 2U, + PA3_PWM_CH3 = 3U, + PA3_ADC_A1 = 8U, + PA4_I2S0_SDA = 0U, + PA4_SPI0_MOSI = 1U, + PA4_UART1_CTS = 2U, + PA4_PWM_CH4 = 3U, + PA4_ADC_A2 = 9U, + PA5_I2S1_SDA = 0U, + PA5_SPI0_MISO = 1U, + PA5_UART1_RTS = 2U, + PA5_PWM_CH5 = 3U, + PA5_ADC_A3 = 10U, + PA6_I2S0_SCLK = 0U, + PA6_UART0_TX = 1U, + PA6_SPI1_MOSI = 2U, + PA6_PWM_CH6 = 3U, + PA6_ADC_A4 = 11U, + PA7_I2S0_WSCLK = 0U, + PA7_PWMR_OUT = 1U, + PA7_SPI1_MISO = 2U, + PA7_PWM_CH7 = 3U, + PA7_ADC_A5 = 12U, + PA8_I2S0_SDA = 0U, + PA8_IIC0_SCL = 1U, + PA8_UART0_RX = 2U, + PA8_PWM_CH8 = 3U, + PA8_ADC_A6 = 13U, + PA9_I2S1_SDA = 0U, + PA9_IIC0_SDA = 1U, + PA9_PWMR_OUT = 2U, + PA9_PWM_CH9 = 3U, + PA9_ADC_A7 = 14U, + PA10_I2S0_MCLK = 0U, + PA10_UART0_TX = 1U, + PA10_SPI1_MOSI = 2U, + PA10_SPI1_MISO = 3U, + PA10_ADC_A8 = 15U, + PA15_IIC0_SCL = 0U, + PA15_SPI0_CS = 1U, + PA15_PWMR_OUT = 2U, + PA15_PWM_CH4 = 3U, + PA15_ADC_A9 = 20U, + PA16_IIC0_SDA = 0U, + PA16_SPI0_SCK = 1U, + PA16_UART1_TX = 2U, + PA16_PWM_CH5 = 3U, + PA16_ADC_A10 = 21U, + PA17_UART0_RX = 0U, + PA17_SPI0_MOSI = 1U, + PA17_I2S0_SCLK = 2U, + PA17_PWM_CH10 = 3U, + PA17_ADC_A11 = 22U, + PA18_UART0_TX = 0U, + PA18_SPI0_MISO = 1U, + PA18_I2S0_WSCLK = 2U, + PA18_PWM_CH11 = 3U, + PA18_ADC_A12 = 23U, + PA19_JTAG_TMS = 0U, + PA19_UART1_RX = 1U, + PA19_I2S1_SCLK = 2U, + PA19_IIC0_SCL = 3U, + PA19_ADC_A13 = 24U, + PA20_JTAG_TCK = 0U, + PA20_UART1_TX = 1U, + PA20_I2S1_WSCLK = 2U, + PA20_IIC0_SDA = 3U, + PA20_ADC_A14 = 25U, + PA21_UART0_CTS = 0U, + PA21_UART1_CTS = 1U, + PA21_I2S0_SDA = 2U, + PA21_IIC0_SCL = 3U, + PA21_ADC_A15 = 26U, + PA22_UART0_RTS = 0U, + PA22_UART1_RTS = 1U, + PA22_I2S1_SDA = 2U, + PA22_IIC0_SDA = 3U, + PA23_IIC0_SCL = 0U, + PA23_UART0_TX = 1U, + PA23_PWM_CH0 = 2U, + PA23_SPI0_CS = 3U, + PA24_IIC0_SDA = 0U, + PA24_UART0_RX = 1U, + PA24_PWM_CH1 = 2U, + PA24_SPI0_SCK = 3U, + PA25_PWMR_OUT = 0U, + PA25_UART0_CTS = 1U, + PA25_PWM_CH2 = 2U, + PA25_SPI0_MOSI = 3U, + PA26_I2S1_MCLK = 0U, + PA26_UART0_RTS = 1U, + PA26_PWM_CH3 = 2U, + PA26_SPI0_MISO = 3U, + PA27_I2S0_SCLK = 0U, + PA27_UART1_RX = 1U, + PA27_PWM_CH4 = 2U, + PA27_SPI1_CS = 3U, + PA28_I2S0_WSCLK = 0U, + PA28_UART1_TX = 1U, + PA28_PWM_CH5 = 2U, + PA28_SPI1_SCK = 3U, + PA29_I2S1_SCLK = 0U, + PA29_UART1_CTS = 1U, + PA29_PWM_CH6 = 2U, + PA29_SPI1_MOSI = 3U, + PA30_I2S1_WSCLK = 0U, + PA30_UART1_RTS = 1U, + PA30_PWM_CH7 = 2U, + PA30_SPI1_MISO = 3U, + PA31_I2S0_SDA = 0U, + PA31_PWMR_OUT = 1U, + PA31_PWM_CH8 = 2U, + PA31_UART0_TX = 3U, + PIN_FUNC_GPIO = 4U, + PIN_FUNC_END = 0xFFFFFFFFU +} pin_func_t; + +#if CONFIG_INTC_CLIC_PLIC +#define CONFIG_IRQ_NUM (64U + PLIC_IRQ_OFFSET) +#else +#define CONFIG_IRQ_NUM 64U +#endif + +///< AHB +#define SPIFLASH_BASE 0x18000000UL +#define SPIFLASH_SIZE 0x800000U +#define SRAM_BASE 0x20000000UL +#define SRAM_SIZE 0x20000U + +#if CONFIG_CPU_XUANTIE_E9XX + +typedef enum { + User_Software_IRQn = 0U, /* User software interrupt */ + Supervisor_Software_IRQn = 1U, /* Supervisor software interrupt */ + Machine_Software_IRQn = 3U, /* Machine software interrupt */ + User_Timer_IRQn = 4U, /* User timer interrupt */ + Supervisor_Timer_IRQn = 5U, /* Supervisor timer interrupt */ + CORET_IRQn = 7U, /* Machine timer interrupt */ + Machine_External_IRQn = 11U, /* Machine external interrupt */ + DW_UART0_IRQn = 16U, + TIM0_IRQn = 18U, /* timer0 Interrupt */ + TIM1_IRQn = 19U, /* timer1 Interrupt */ + TIM2_IRQn = 20U, /* timer2 Interrupt */ + TIM3_IRQn = 21U, /* timer3 Interrupt */ +} irqn_type_t; + +#define DW_UART0_BASE 0x40015000UL +#define DW_TIMER0_BASE 0x40011000UL +#define DW_TIMER0_SIZE 0x14U +#define DW_TIMER1_BASE (DW_TIMER0_BASE+DW_TIMER0_SIZE) +#define DW_TIMER1_SIZE DW_TIMER0_SIZE +#define DW_TIMER2_BASE 0x40011028UL +#define DW_TIMER2_SIZE 0x14U +#define DW_TIMER3_BASE (DW_TIMER2_BASE+DW_TIMER2_SIZE) +#define DW_TIMER3_SIZE DW_TIMER2_SIZE +#if CONFIG_SUPPORT_NMI_DEMO +/* fake irq is not work, just for nmi test with smartl fpga(connected TIMER4 to nmi-exception on soc bit of smartl) */ +#define FAKE_IRQ_TIMER4 (-1) +#define DW_TIMER4_BASE (0x40021000UL) +#endif + +#else + +/* ------------------------- Interrupt Number Definition ------------------------ */ + +#define Supervisor_Software_IRQn (1U) +#define Machine_Software_IRQn (3U) +#define Supervisor_Timer_IRQn (5U) +#define CORET_IRQn (7U) +#define Supervisor_External_IRQn (9U) +#define Machine_External_IRQn (11U) +#define L1_CACHE_ECC_IRQn (16U) + +#if CONFIG_BOARD_XIAOHUI_EVB + +#if CONFIG_INTC_CLIC_PLIC +typedef enum IRQn { + L2_CACHE_ECC_IRQn = 1U + PLIC_IRQ_OFFSET, /* l2 cache ecc Interrupt */ + + DW_UART0_IRQn = 20U + PLIC_IRQ_OFFSET, /* uart Interrupt */ + TIM0_IRQn = 25U, /* timer0 Interrupt for CLIC*/ + TIM1_IRQn = 26U, /* timer1 Interrupt for CLIC*/ + TIM2_IRQn = 27U + PLIC_IRQ_OFFSET, /* timer2 Interrupt */ + TIM3_IRQn = 28U + PLIC_IRQ_OFFSET, /* timer3 Interrupt */ + END_IRQn = 1024U + PLIC_IRQ_OFFSET +} irqn_type_t; +#else +/* extern irq number, 1-16 are reserved for inner-cpu */ +typedef enum IRQn { + L2_CACHE_ECC_IRQn = 1U, /* l2 cache ecc Interrupt */ + + DW_UART0_IRQn = 20U, /* uart Interrupt */ + TIM0_IRQn = 25U, /* timer0 Interrupt */ + TIM1_IRQn = 26U, /* timer1 Interrupt */ + TIM2_IRQn = 27U, /* timer2 Interrupt */ + TIM3_IRQn = 28U, /* timer3 Interrupt */ +} irqn_type_t; +#endif /* CONFIG_INTC_CLIC_PLIC */ + +#define DW_UART0_BASE (0x1900d000UL) +#define DW_TIMER0_BASE (0x19001000UL) +#define DW_TIMER1_BASE (0x19001014UL) +#define DW_TIMER2_BASE (0x19001028UL) +#define DW_TIMER3_BASE (0x1900103CUL) + +#else +#error "Not support soc!!!" +#endif /* CONFIG_BOARD_XIAOHUI_EVB */ + +#endif /* end exx*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _SOC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/sys_clk.h b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/sys_clk.h new file mode 100644 index 00000000000..3d74f5e9a44 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/include/sys_clk.h @@ -0,0 +1,117 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file sys_clk.h + * @brief header file for setting system frequency. + * @version V1.0 + * @date 9. April 2020 + ******************************************************************************/ +#ifndef _SYS_CLK_H_ +#define _SYS_CLK_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PMU_REG_BASE (wj_pmu_reg_t *)WJ_PMU_BASE + +typedef enum { + IHS_CLK = 0U, /* internal high speed clock */ + EHS_CLK, /* external high speed clock */ + ILS_CLK, /* internal low speed clock */ + ELS_CLK, /* external low speed clock */ + PLL_CLK /* PLL clock */ +} clk_src_t; + +typedef enum { + CPU_24MHZ = 24000000U +} sys_freq_t; + + +/* pllclkout : ( pllclkin / 2)*( FN + Frac/4096 ) */ +typedef struct { + + uint32_t pll_is_used; /* pll is used */ + + uint32_t pll_source; /* select pll input source clock */ + + uint32_t pll_src_clk_divider; /* ratio between pll_srcclk clock and pll_clkin clock */ + + uint32_t fn; /* integer value of frequency division */ + + uint32_t frac; /* decimal value of frequency division */ + +} pll_config_t; + + +typedef struct { + uint32_t system_clk; /* system clock */ + + pll_config_t pll_config; /* pll config struct */ + + uint32_t sys_clk_source; /* select sysclk source clock */ + + uint32_t rtc_clk_source; /* select rtcclk source clock */ + + uint32_t mclk_divider; /* ratio between fs_mclk clock and mclk clock */ + + uint32_t apb0_clk_divider; /* ratio between mclk clock and apb0 clock */ + + uint32_t apb1_clk_divider; /* ratio between mclk clock and apb1 clock */ + +} system_clk_config_t; + +typedef enum { + CLK_DIV1 = 0U, +} apb_div_t; + +typedef enum { + PLL_FN_18 = 0U, +} pll_fn_t; + +typedef enum { + UART0_CLK, +} clk_module_t; + + +/** + \brief Set the system clock according to the parameter + \param[in] config system clock config. + \return error code +*/ +csi_error_t soc_sysclk_config(system_clk_config_t *config); + +/** + \brief Set iic reset + \param[in] idx iic idx. + \return Null +*/ +void soc_reset_iic(uint32_t idx); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_CLK_H_ */ + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/SConscript b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/SConscript new file mode 100644 index 00000000000..20f7689c53c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/SConscript b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/SConscript new file mode 100644 index 00000000000..781cbc7175a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/SConscript @@ -0,0 +1,16 @@ +# RT-Thread building script for bridge + +import os +from building import * + +Import('rtconfig') + +cwd = GetCurrentDir() +group = [] +list = os.listdir(cwd) + +# add startup code files +if rtconfig.CPU in list : + group = group + SConscript(os.path.join(rtconfig.CPU, 'SConscript')) + +Return('group') diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/startup.S new file mode 100644 index 00000000000..745487ab6d3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/startup.S @@ -0,0 +1,128 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler + j Default_Handler + j Default_Handler + j Default_Handler + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#else + la sp, g_top_irqstack +#endif + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/system.c new file mode 100644 index 00000000000..ba5e05f515a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/system.c @@ -0,0 +1,274 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(MMU_MODE_32); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/vectors.S new file mode 100644 index 00000000000..2f728ddc35d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906/vectors.S @@ -0,0 +1,412 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + csrw mscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + mret + + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/startup.S new file mode 100644 index 00000000000..745487ab6d3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/startup.S @@ -0,0 +1,128 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler + j Default_Handler + j Default_Handler + j Default_Handler + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#else + la sp, g_top_irqstack +#endif + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/system.c new file mode 100644 index 00000000000..ba5e05f515a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/system.c @@ -0,0 +1,274 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(MMU_MODE_32); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/vectors.S new file mode 100644 index 00000000000..2f728ddc35d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fd/vectors.S @@ -0,0 +1,412 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + csrw mscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + mret + + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/startup.S new file mode 100644 index 00000000000..745487ab6d3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/startup.S @@ -0,0 +1,128 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler + j Default_Handler + j Default_Handler + j Default_Handler + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#else + la sp, g_top_irqstack +#endif + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/system.c new file mode 100644 index 00000000000..ba5e05f515a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/system.c @@ -0,0 +1,274 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(MMU_MODE_32); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/vectors.S new file mode 100644 index 00000000000..2f728ddc35d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c906fdv/vectors.S @@ -0,0 +1,412 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + csrw mscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + mret + + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/startup.S new file mode 100644 index 00000000000..38a84acde3f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + lw a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/system.c new file mode 100644 index 00000000000..cccef03fd16 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/system.c @@ -0,0 +1,326 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix */ + status &= ~(1ul << 0); +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_MS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/vectors.S new file mode 100644 index 00000000000..ef32af346ff --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907-rv32/vectors.S @@ -0,0 +1,842 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, sscratch + sret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + store_x s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + +#if __riscv_xlen == 64 + addi sp, sp, -(140+140) + store_x x1, ( 0 + 0 )(sp) + store_x x3, ( 8 + 8 )(sp) + store_x x4, ( 12+ 12)(sp) + store_x x5, ( 16+ 16)(sp) + store_x x6, ( 20+ 20)(sp) + store_x x7, ( 24+ 24)(sp) + store_x x8, ( 28+ 28)(sp) + store_x x9, ( 32+ 32)(sp) + store_x x10,( 36+ 36)(sp) + store_x x11,( 40+ 40)(sp) + store_x x12,( 44+ 44)(sp) + store_x x13,( 48+ 48)(sp) + store_x x14,( 52+ 52)(sp) + store_x x15,( 56+ 56)(sp) + store_x x16,( 60+ 60)(sp) + store_x x17,( 64+ 64)(sp) + store_x x18,( 68+ 68)(sp) + store_x x19,( 72+ 72)(sp) + store_x x20,( 76+ 76)(sp) + store_x x21,( 80+ 80)(sp) + store_x x22,( 84+ 84)(sp) + store_x x23,( 88+ 88)(sp) + store_x x24,( 92+ 92)(sp) + store_x x25,( 96+ 96)(sp) + store_x x26,(100+100)(sp) + store_x x27,(104+104)(sp) + store_x x28,(108+108)(sp) + store_x x29,(112+112)(sp) + store_x x30,(116+116)(sp) + store_x x31,(120+120)(sp) + csrr a0, mepc + store_x a0, (124+124)(sp) + csrr a0, mstatus + store_x a0, (128+128)(sp) + csrr a0, mcause + store_x a0, (132+132)(sp) + csrr a0, mtval + store_x a0, (136+136)(sp) + csrr a0, mscratch + store_x a0, ( 4 + 4 )(sp) +#else + addi sp, sp, -140 + store_x x1, ( 0 )(sp) + store_x x3, ( 8 )(sp) + store_x x4, ( 12)(sp) + store_x x5, ( 16)(sp) + store_x x6, ( 20)(sp) + store_x x7, ( 24)(sp) + store_x x8, ( 28)(sp) + store_x x9, ( 32)(sp) + store_x x10,( 36)(sp) + store_x x11,( 40)(sp) + store_x x12,( 44)(sp) + store_x x13,( 48)(sp) + store_x x14,( 52)(sp) + store_x x15,( 56)(sp) + store_x x16,( 60)(sp) + store_x x17,( 64)(sp) + store_x x18,( 68)(sp) + store_x x19,( 72)(sp) + store_x x20,( 76)(sp) + store_x x21,( 80)(sp) + store_x x22,( 84)(sp) + store_x x23,( 88)(sp) + store_x x24,( 92)(sp) + store_x x25,( 96)(sp) + store_x x26,(100)(sp) + store_x x27,(104)(sp) + store_x x28,(108)(sp) + store_x x29,(112)(sp) + store_x x30,(116)(sp) + store_x x31,(120)(sp) + csrr a0, mepc + store_x a0, (124)(sp) + csrr a0, mstatus + store_x a0, (128)(sp) + csrr a0, mcause + store_x a0, (132)(sp) + csrr a0, mtval + store_x a0, (136)(sp) + csrr a0, mscratch + store_x a0, ( 4 )(sp) +#endif + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/system.c new file mode 100644 index 00000000000..cccef03fd16 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/system.c @@ -0,0 +1,326 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix */ + status &= ~(1ul << 0); +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_MS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/vectors.S new file mode 100644 index 00000000000..ef32af346ff --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907/vectors.S @@ -0,0 +1,842 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, sscratch + sret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + store_x s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + +#if __riscv_xlen == 64 + addi sp, sp, -(140+140) + store_x x1, ( 0 + 0 )(sp) + store_x x3, ( 8 + 8 )(sp) + store_x x4, ( 12+ 12)(sp) + store_x x5, ( 16+ 16)(sp) + store_x x6, ( 20+ 20)(sp) + store_x x7, ( 24+ 24)(sp) + store_x x8, ( 28+ 28)(sp) + store_x x9, ( 32+ 32)(sp) + store_x x10,( 36+ 36)(sp) + store_x x11,( 40+ 40)(sp) + store_x x12,( 44+ 44)(sp) + store_x x13,( 48+ 48)(sp) + store_x x14,( 52+ 52)(sp) + store_x x15,( 56+ 56)(sp) + store_x x16,( 60+ 60)(sp) + store_x x17,( 64+ 64)(sp) + store_x x18,( 68+ 68)(sp) + store_x x19,( 72+ 72)(sp) + store_x x20,( 76+ 76)(sp) + store_x x21,( 80+ 80)(sp) + store_x x22,( 84+ 84)(sp) + store_x x23,( 88+ 88)(sp) + store_x x24,( 92+ 92)(sp) + store_x x25,( 96+ 96)(sp) + store_x x26,(100+100)(sp) + store_x x27,(104+104)(sp) + store_x x28,(108+108)(sp) + store_x x29,(112+112)(sp) + store_x x30,(116+116)(sp) + store_x x31,(120+120)(sp) + csrr a0, mepc + store_x a0, (124+124)(sp) + csrr a0, mstatus + store_x a0, (128+128)(sp) + csrr a0, mcause + store_x a0, (132+132)(sp) + csrr a0, mtval + store_x a0, (136+136)(sp) + csrr a0, mscratch + store_x a0, ( 4 + 4 )(sp) +#else + addi sp, sp, -140 + store_x x1, ( 0 )(sp) + store_x x3, ( 8 )(sp) + store_x x4, ( 12)(sp) + store_x x5, ( 16)(sp) + store_x x6, ( 20)(sp) + store_x x7, ( 24)(sp) + store_x x8, ( 28)(sp) + store_x x9, ( 32)(sp) + store_x x10,( 36)(sp) + store_x x11,( 40)(sp) + store_x x12,( 44)(sp) + store_x x13,( 48)(sp) + store_x x14,( 52)(sp) + store_x x15,( 56)(sp) + store_x x16,( 60)(sp) + store_x x17,( 64)(sp) + store_x x18,( 68)(sp) + store_x x19,( 72)(sp) + store_x x20,( 76)(sp) + store_x x21,( 80)(sp) + store_x x22,( 84)(sp) + store_x x23,( 88)(sp) + store_x x24,( 92)(sp) + store_x x25,( 96)(sp) + store_x x26,(100)(sp) + store_x x27,(104)(sp) + store_x x28,(108)(sp) + store_x x29,(112)(sp) + store_x x30,(116)(sp) + store_x x31,(120)(sp) + csrr a0, mepc + store_x a0, (124)(sp) + csrr a0, mstatus + store_x a0, (128)(sp) + csrr a0, mcause + store_x a0, (132)(sp) + csrr a0, mtval + store_x a0, (136)(sp) + csrr a0, mscratch + store_x a0, ( 4 )(sp) +#endif + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/startup.S new file mode 100644 index 00000000000..38a84acde3f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + lw a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/system.c new file mode 100644 index 00000000000..cccef03fd16 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/system.c @@ -0,0 +1,326 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix */ + status &= ~(1ul << 0); +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_MS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/vectors.S new file mode 100644 index 00000000000..ef32af346ff --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd-rv32/vectors.S @@ -0,0 +1,842 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, sscratch + sret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + store_x s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + +#if __riscv_xlen == 64 + addi sp, sp, -(140+140) + store_x x1, ( 0 + 0 )(sp) + store_x x3, ( 8 + 8 )(sp) + store_x x4, ( 12+ 12)(sp) + store_x x5, ( 16+ 16)(sp) + store_x x6, ( 20+ 20)(sp) + store_x x7, ( 24+ 24)(sp) + store_x x8, ( 28+ 28)(sp) + store_x x9, ( 32+ 32)(sp) + store_x x10,( 36+ 36)(sp) + store_x x11,( 40+ 40)(sp) + store_x x12,( 44+ 44)(sp) + store_x x13,( 48+ 48)(sp) + store_x x14,( 52+ 52)(sp) + store_x x15,( 56+ 56)(sp) + store_x x16,( 60+ 60)(sp) + store_x x17,( 64+ 64)(sp) + store_x x18,( 68+ 68)(sp) + store_x x19,( 72+ 72)(sp) + store_x x20,( 76+ 76)(sp) + store_x x21,( 80+ 80)(sp) + store_x x22,( 84+ 84)(sp) + store_x x23,( 88+ 88)(sp) + store_x x24,( 92+ 92)(sp) + store_x x25,( 96+ 96)(sp) + store_x x26,(100+100)(sp) + store_x x27,(104+104)(sp) + store_x x28,(108+108)(sp) + store_x x29,(112+112)(sp) + store_x x30,(116+116)(sp) + store_x x31,(120+120)(sp) + csrr a0, mepc + store_x a0, (124+124)(sp) + csrr a0, mstatus + store_x a0, (128+128)(sp) + csrr a0, mcause + store_x a0, (132+132)(sp) + csrr a0, mtval + store_x a0, (136+136)(sp) + csrr a0, mscratch + store_x a0, ( 4 + 4 )(sp) +#else + addi sp, sp, -140 + store_x x1, ( 0 )(sp) + store_x x3, ( 8 )(sp) + store_x x4, ( 12)(sp) + store_x x5, ( 16)(sp) + store_x x6, ( 20)(sp) + store_x x7, ( 24)(sp) + store_x x8, ( 28)(sp) + store_x x9, ( 32)(sp) + store_x x10,( 36)(sp) + store_x x11,( 40)(sp) + store_x x12,( 44)(sp) + store_x x13,( 48)(sp) + store_x x14,( 52)(sp) + store_x x15,( 56)(sp) + store_x x16,( 60)(sp) + store_x x17,( 64)(sp) + store_x x18,( 68)(sp) + store_x x19,( 72)(sp) + store_x x20,( 76)(sp) + store_x x21,( 80)(sp) + store_x x22,( 84)(sp) + store_x x23,( 88)(sp) + store_x x24,( 92)(sp) + store_x x25,( 96)(sp) + store_x x26,(100)(sp) + store_x x27,(104)(sp) + store_x x28,(108)(sp) + store_x x29,(112)(sp) + store_x x30,(116)(sp) + store_x x31,(120)(sp) + csrr a0, mepc + store_x a0, (124)(sp) + csrr a0, mstatus + store_x a0, (128)(sp) + csrr a0, mcause + store_x a0, (132)(sp) + csrr a0, mtval + store_x a0, (136)(sp) + csrr a0, mscratch + store_x a0, ( 4 )(sp) +#endif + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/system.c new file mode 100644 index 00000000000..cccef03fd16 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/system.c @@ -0,0 +1,326 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix */ + status &= ~(1ul << 0); +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_MS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/vectors.S new file mode 100644 index 00000000000..ef32af346ff --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fd/vectors.S @@ -0,0 +1,842 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, sscratch + sret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + store_x s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + +#if __riscv_xlen == 64 + addi sp, sp, -(140+140) + store_x x1, ( 0 + 0 )(sp) + store_x x3, ( 8 + 8 )(sp) + store_x x4, ( 12+ 12)(sp) + store_x x5, ( 16+ 16)(sp) + store_x x6, ( 20+ 20)(sp) + store_x x7, ( 24+ 24)(sp) + store_x x8, ( 28+ 28)(sp) + store_x x9, ( 32+ 32)(sp) + store_x x10,( 36+ 36)(sp) + store_x x11,( 40+ 40)(sp) + store_x x12,( 44+ 44)(sp) + store_x x13,( 48+ 48)(sp) + store_x x14,( 52+ 52)(sp) + store_x x15,( 56+ 56)(sp) + store_x x16,( 60+ 60)(sp) + store_x x17,( 64+ 64)(sp) + store_x x18,( 68+ 68)(sp) + store_x x19,( 72+ 72)(sp) + store_x x20,( 76+ 76)(sp) + store_x x21,( 80+ 80)(sp) + store_x x22,( 84+ 84)(sp) + store_x x23,( 88+ 88)(sp) + store_x x24,( 92+ 92)(sp) + store_x x25,( 96+ 96)(sp) + store_x x26,(100+100)(sp) + store_x x27,(104+104)(sp) + store_x x28,(108+108)(sp) + store_x x29,(112+112)(sp) + store_x x30,(116+116)(sp) + store_x x31,(120+120)(sp) + csrr a0, mepc + store_x a0, (124+124)(sp) + csrr a0, mstatus + store_x a0, (128+128)(sp) + csrr a0, mcause + store_x a0, (132+132)(sp) + csrr a0, mtval + store_x a0, (136+136)(sp) + csrr a0, mscratch + store_x a0, ( 4 + 4 )(sp) +#else + addi sp, sp, -140 + store_x x1, ( 0 )(sp) + store_x x3, ( 8 )(sp) + store_x x4, ( 12)(sp) + store_x x5, ( 16)(sp) + store_x x6, ( 20)(sp) + store_x x7, ( 24)(sp) + store_x x8, ( 28)(sp) + store_x x9, ( 32)(sp) + store_x x10,( 36)(sp) + store_x x11,( 40)(sp) + store_x x12,( 44)(sp) + store_x x13,( 48)(sp) + store_x x14,( 52)(sp) + store_x x15,( 56)(sp) + store_x x16,( 60)(sp) + store_x x17,( 64)(sp) + store_x x18,( 68)(sp) + store_x x19,( 72)(sp) + store_x x20,( 76)(sp) + store_x x21,( 80)(sp) + store_x x22,( 84)(sp) + store_x x23,( 88)(sp) + store_x x24,( 92)(sp) + store_x x25,( 96)(sp) + store_x x26,(100)(sp) + store_x x27,(104)(sp) + store_x x28,(108)(sp) + store_x x29,(112)(sp) + store_x x30,(116)(sp) + store_x x31,(120)(sp) + csrr a0, mepc + store_x a0, (124)(sp) + csrr a0, mstatus + store_x a0, (128)(sp) + csrr a0, mcause + store_x a0, (132)(sp) + csrr a0, mtval + store_x a0, (136)(sp) + csrr a0, mscratch + store_x a0, ( 4 )(sp) +#endif + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/startup.S new file mode 100644 index 00000000000..38a84acde3f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + lw a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/system.c new file mode 100644 index 00000000000..cccef03fd16 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/system.c @@ -0,0 +1,326 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix */ + status &= ~(1ul << 0); +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_MS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/vectors.S new file mode 100644 index 00000000000..ef32af346ff --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv-rv32/vectors.S @@ -0,0 +1,842 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, sscratch + sret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + store_x s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + +#if __riscv_xlen == 64 + addi sp, sp, -(140+140) + store_x x1, ( 0 + 0 )(sp) + store_x x3, ( 8 + 8 )(sp) + store_x x4, ( 12+ 12)(sp) + store_x x5, ( 16+ 16)(sp) + store_x x6, ( 20+ 20)(sp) + store_x x7, ( 24+ 24)(sp) + store_x x8, ( 28+ 28)(sp) + store_x x9, ( 32+ 32)(sp) + store_x x10,( 36+ 36)(sp) + store_x x11,( 40+ 40)(sp) + store_x x12,( 44+ 44)(sp) + store_x x13,( 48+ 48)(sp) + store_x x14,( 52+ 52)(sp) + store_x x15,( 56+ 56)(sp) + store_x x16,( 60+ 60)(sp) + store_x x17,( 64+ 64)(sp) + store_x x18,( 68+ 68)(sp) + store_x x19,( 72+ 72)(sp) + store_x x20,( 76+ 76)(sp) + store_x x21,( 80+ 80)(sp) + store_x x22,( 84+ 84)(sp) + store_x x23,( 88+ 88)(sp) + store_x x24,( 92+ 92)(sp) + store_x x25,( 96+ 96)(sp) + store_x x26,(100+100)(sp) + store_x x27,(104+104)(sp) + store_x x28,(108+108)(sp) + store_x x29,(112+112)(sp) + store_x x30,(116+116)(sp) + store_x x31,(120+120)(sp) + csrr a0, mepc + store_x a0, (124+124)(sp) + csrr a0, mstatus + store_x a0, (128+128)(sp) + csrr a0, mcause + store_x a0, (132+132)(sp) + csrr a0, mtval + store_x a0, (136+136)(sp) + csrr a0, mscratch + store_x a0, ( 4 + 4 )(sp) +#else + addi sp, sp, -140 + store_x x1, ( 0 )(sp) + store_x x3, ( 8 )(sp) + store_x x4, ( 12)(sp) + store_x x5, ( 16)(sp) + store_x x6, ( 20)(sp) + store_x x7, ( 24)(sp) + store_x x8, ( 28)(sp) + store_x x9, ( 32)(sp) + store_x x10,( 36)(sp) + store_x x11,( 40)(sp) + store_x x12,( 44)(sp) + store_x x13,( 48)(sp) + store_x x14,( 52)(sp) + store_x x15,( 56)(sp) + store_x x16,( 60)(sp) + store_x x17,( 64)(sp) + store_x x18,( 68)(sp) + store_x x19,( 72)(sp) + store_x x20,( 76)(sp) + store_x x21,( 80)(sp) + store_x x22,( 84)(sp) + store_x x23,( 88)(sp) + store_x x24,( 92)(sp) + store_x x25,( 96)(sp) + store_x x26,(100)(sp) + store_x x27,(104)(sp) + store_x x28,(108)(sp) + store_x x29,(112)(sp) + store_x x30,(116)(sp) + store_x x31,(120)(sp) + csrr a0, mepc + store_x a0, (124)(sp) + csrr a0, mstatus + store_x a0, (128)(sp) + csrr a0, mcause + store_x a0, (132)(sp) + csrr a0, mtval + store_x a0, (136)(sp) + csrr a0, mscratch + store_x a0, ( 4 )(sp) +#endif + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/system.c new file mode 100644 index 00000000000..cccef03fd16 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/system.c @@ -0,0 +1,326 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix */ + status &= ~(1ul << 0); +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_MS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/vectors.S new file mode 100644 index 00000000000..ef32af346ff --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdv/vectors.S @@ -0,0 +1,842 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, sscratch + sret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + store_x s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + +#if __riscv_xlen == 64 + addi sp, sp, -(140+140) + store_x x1, ( 0 + 0 )(sp) + store_x x3, ( 8 + 8 )(sp) + store_x x4, ( 12+ 12)(sp) + store_x x5, ( 16+ 16)(sp) + store_x x6, ( 20+ 20)(sp) + store_x x7, ( 24+ 24)(sp) + store_x x8, ( 28+ 28)(sp) + store_x x9, ( 32+ 32)(sp) + store_x x10,( 36+ 36)(sp) + store_x x11,( 40+ 40)(sp) + store_x x12,( 44+ 44)(sp) + store_x x13,( 48+ 48)(sp) + store_x x14,( 52+ 52)(sp) + store_x x15,( 56+ 56)(sp) + store_x x16,( 60+ 60)(sp) + store_x x17,( 64+ 64)(sp) + store_x x18,( 68+ 68)(sp) + store_x x19,( 72+ 72)(sp) + store_x x20,( 76+ 76)(sp) + store_x x21,( 80+ 80)(sp) + store_x x22,( 84+ 84)(sp) + store_x x23,( 88+ 88)(sp) + store_x x24,( 92+ 92)(sp) + store_x x25,( 96+ 96)(sp) + store_x x26,(100+100)(sp) + store_x x27,(104+104)(sp) + store_x x28,(108+108)(sp) + store_x x29,(112+112)(sp) + store_x x30,(116+116)(sp) + store_x x31,(120+120)(sp) + csrr a0, mepc + store_x a0, (124+124)(sp) + csrr a0, mstatus + store_x a0, (128+128)(sp) + csrr a0, mcause + store_x a0, (132+132)(sp) + csrr a0, mtval + store_x a0, (136+136)(sp) + csrr a0, mscratch + store_x a0, ( 4 + 4 )(sp) +#else + addi sp, sp, -140 + store_x x1, ( 0 )(sp) + store_x x3, ( 8 )(sp) + store_x x4, ( 12)(sp) + store_x x5, ( 16)(sp) + store_x x6, ( 20)(sp) + store_x x7, ( 24)(sp) + store_x x8, ( 28)(sp) + store_x x9, ( 32)(sp) + store_x x10,( 36)(sp) + store_x x11,( 40)(sp) + store_x x12,( 44)(sp) + store_x x13,( 48)(sp) + store_x x14,( 52)(sp) + store_x x15,( 56)(sp) + store_x x16,( 60)(sp) + store_x x17,( 64)(sp) + store_x x18,( 68)(sp) + store_x x19,( 72)(sp) + store_x x20,( 76)(sp) + store_x x21,( 80)(sp) + store_x x22,( 84)(sp) + store_x x23,( 88)(sp) + store_x x24,( 92)(sp) + store_x x25,( 96)(sp) + store_x x26,(100)(sp) + store_x x27,(104)(sp) + store_x x28,(108)(sp) + store_x x29,(112)(sp) + store_x x30,(116)(sp) + store_x x31,(120)(sp) + csrr a0, mepc + store_x a0, (124)(sp) + csrr a0, mstatus + store_x a0, (128)(sp) + csrr a0, mcause + store_x a0, (132)(sp) + csrr a0, mtval + store_x a0, (136)(sp) + csrr a0, mscratch + store_x a0, ( 4 )(sp) +#endif + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/startup.S new file mode 100644 index 00000000000..38a84acde3f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + lw a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/system.c new file mode 100644 index 00000000000..cccef03fd16 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/system.c @@ -0,0 +1,326 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix */ + status &= ~(1ul << 0); +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_MS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/vectors.S new file mode 100644 index 00000000000..ef32af346ff --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm-rv32/vectors.S @@ -0,0 +1,842 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, sscratch + sret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + store_x s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + +#if __riscv_xlen == 64 + addi sp, sp, -(140+140) + store_x x1, ( 0 + 0 )(sp) + store_x x3, ( 8 + 8 )(sp) + store_x x4, ( 12+ 12)(sp) + store_x x5, ( 16+ 16)(sp) + store_x x6, ( 20+ 20)(sp) + store_x x7, ( 24+ 24)(sp) + store_x x8, ( 28+ 28)(sp) + store_x x9, ( 32+ 32)(sp) + store_x x10,( 36+ 36)(sp) + store_x x11,( 40+ 40)(sp) + store_x x12,( 44+ 44)(sp) + store_x x13,( 48+ 48)(sp) + store_x x14,( 52+ 52)(sp) + store_x x15,( 56+ 56)(sp) + store_x x16,( 60+ 60)(sp) + store_x x17,( 64+ 64)(sp) + store_x x18,( 68+ 68)(sp) + store_x x19,( 72+ 72)(sp) + store_x x20,( 76+ 76)(sp) + store_x x21,( 80+ 80)(sp) + store_x x22,( 84+ 84)(sp) + store_x x23,( 88+ 88)(sp) + store_x x24,( 92+ 92)(sp) + store_x x25,( 96+ 96)(sp) + store_x x26,(100+100)(sp) + store_x x27,(104+104)(sp) + store_x x28,(108+108)(sp) + store_x x29,(112+112)(sp) + store_x x30,(116+116)(sp) + store_x x31,(120+120)(sp) + csrr a0, mepc + store_x a0, (124+124)(sp) + csrr a0, mstatus + store_x a0, (128+128)(sp) + csrr a0, mcause + store_x a0, (132+132)(sp) + csrr a0, mtval + store_x a0, (136+136)(sp) + csrr a0, mscratch + store_x a0, ( 4 + 4 )(sp) +#else + addi sp, sp, -140 + store_x x1, ( 0 )(sp) + store_x x3, ( 8 )(sp) + store_x x4, ( 12)(sp) + store_x x5, ( 16)(sp) + store_x x6, ( 20)(sp) + store_x x7, ( 24)(sp) + store_x x8, ( 28)(sp) + store_x x9, ( 32)(sp) + store_x x10,( 36)(sp) + store_x x11,( 40)(sp) + store_x x12,( 44)(sp) + store_x x13,( 48)(sp) + store_x x14,( 52)(sp) + store_x x15,( 56)(sp) + store_x x16,( 60)(sp) + store_x x17,( 64)(sp) + store_x x18,( 68)(sp) + store_x x19,( 72)(sp) + store_x x20,( 76)(sp) + store_x x21,( 80)(sp) + store_x x22,( 84)(sp) + store_x x23,( 88)(sp) + store_x x24,( 92)(sp) + store_x x25,( 96)(sp) + store_x x26,(100)(sp) + store_x x27,(104)(sp) + store_x x28,(108)(sp) + store_x x29,(112)(sp) + store_x x30,(116)(sp) + store_x x31,(120)(sp) + csrr a0, mepc + store_x a0, (124)(sp) + csrr a0, mstatus + store_x a0, (128)(sp) + csrr a0, mcause + store_x a0, (132)(sp) + csrr a0, mtval + store_x a0, (136)(sp) + csrr a0, mscratch + store_x a0, ( 4 )(sp) +#endif + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/system.c new file mode 100644 index 00000000000..cccef03fd16 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/system.c @@ -0,0 +1,326 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix */ + status &= ~(1ul << 0); +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif +#if __riscv_matrix || __riscv_xtheadmatrix + /* enable matrix ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_MS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/vectors.S new file mode 100644 index 00000000000..ef32af346ff --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c907fdvm/vectors.S @@ -0,0 +1,842 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, sepc + store_x t0, (68+68)(sp) + csrr t0, sstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, sepc + store_x t0, (68)(sp) + csrr t0, sstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72+72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw sepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + load_x t0, (72)(sp) + csrw sstatus, t0 +#endif + load_x t0, (68)(sp) + csrw sepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, sscratch + sret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + store_x t0, (0)(sp) + store_x t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + store_x s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if __riscv_xlen == 64 + addi sp, sp, -(76+76) + store_x t0, (4+4)(sp) + store_x t1, (8+8)(sp) + store_x t2, (12+12)(sp) + + csrr t0, mepc + store_x t0, (68+68)(sp) + csrr t0, mstatus + store_x t0, (72+72)(sp) + + store_x ra, (0 +0 )(sp) + store_x a0, (16+16)(sp) + store_x a1, (20+20)(sp) + store_x a2, (24+24)(sp) + store_x a3, (28+28)(sp) + store_x a4, (32+32)(sp) + store_x a5, (36+36)(sp) + store_x a6, (40+40)(sp) + store_x a7, (44+44)(sp) + store_x t3, (48+48)(sp) + store_x t4, (52+52)(sp) + store_x t5, (56+56)(sp) + store_x t6, (60+60)(sp) +#else + addi sp, sp, -76 + store_x t0, (4)(sp) + store_x t1, (8)(sp) + store_x t2, (12)(sp) + + csrr t0, mepc + store_x t0, (68)(sp) + csrr t0, mstatus + store_x t0, (72)(sp) + + store_x ra, (0)(sp) + store_x a0, (16)(sp) + store_x a1, (20)(sp) + store_x a2, (24)(sp) + store_x a3, (28)(sp) + store_x a4, (32)(sp) + store_x a5, (36)(sp) + store_x a6, (40)(sp) + store_x a7, (44)(sp) + store_x t3, (48)(sp) + store_x t4, (52)(sp) + store_x t5, (56)(sp) + store_x t6, (60)(sp) +#endif + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + SAVE_MATRIX_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY || CONFIG_CHECK_MATRIX_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_MATRIX_REGISTERS + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if __riscv_xlen == 64 +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72+72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68+68)(sp) + csrw mepc, t0 + + load_x ra, (0 +0 )(sp) + load_x t0, (4 +4 )(sp) + load_x t1, (8 +8 )(sp) + load_x t2, (12+12)(sp) + load_x a0, (16+16)(sp) + load_x a1, (20+20)(sp) + load_x a2, (24+24)(sp) + load_x a3, (28+28)(sp) + load_x a4, (32+32)(sp) + load_x a5, (36+36)(sp) + load_x a6, (40+40)(sp) + load_x a7, (44+44)(sp) + load_x t3, (48+48)(sp) + load_x t4, (52+52)(sp) + load_x t5, (56+56)(sp) + load_x t6, (60+60)(sp) + addi sp, sp, (76+76) +#else +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) && (!CONFIG_CHECK_MATRIX_DIRTY) + load_x t0, (72)(sp) + csrw mstatus, t0 +#endif + load_x t0, (68)(sp) + csrw mepc, t0 + + load_x ra, (0)(sp) + load_x t0, (4)(sp) + load_x t1, (8)(sp) + load_x t2, (12)(sp) + load_x a0, (16)(sp) + load_x a1, (20)(sp) + load_x a2, (24)(sp) + load_x a3, (28)(sp) + load_x a4, (32)(sp) + load_x a5, (36)(sp) + load_x a6, (40)(sp) + load_x a7, (44)(sp) + load_x t3, (48)(sp) + load_x t4, (52)(sp) + load_x t5, (56)(sp) + load_x t6, (60)(sp) + addi sp, sp, (76) +#endif + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + load_x t0, (0)(sp) + load_x t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + +#if __riscv_xlen == 64 + addi sp, sp, -(140+140) + store_x x1, ( 0 + 0 )(sp) + store_x x3, ( 8 + 8 )(sp) + store_x x4, ( 12+ 12)(sp) + store_x x5, ( 16+ 16)(sp) + store_x x6, ( 20+ 20)(sp) + store_x x7, ( 24+ 24)(sp) + store_x x8, ( 28+ 28)(sp) + store_x x9, ( 32+ 32)(sp) + store_x x10,( 36+ 36)(sp) + store_x x11,( 40+ 40)(sp) + store_x x12,( 44+ 44)(sp) + store_x x13,( 48+ 48)(sp) + store_x x14,( 52+ 52)(sp) + store_x x15,( 56+ 56)(sp) + store_x x16,( 60+ 60)(sp) + store_x x17,( 64+ 64)(sp) + store_x x18,( 68+ 68)(sp) + store_x x19,( 72+ 72)(sp) + store_x x20,( 76+ 76)(sp) + store_x x21,( 80+ 80)(sp) + store_x x22,( 84+ 84)(sp) + store_x x23,( 88+ 88)(sp) + store_x x24,( 92+ 92)(sp) + store_x x25,( 96+ 96)(sp) + store_x x26,(100+100)(sp) + store_x x27,(104+104)(sp) + store_x x28,(108+108)(sp) + store_x x29,(112+112)(sp) + store_x x30,(116+116)(sp) + store_x x31,(120+120)(sp) + csrr a0, mepc + store_x a0, (124+124)(sp) + csrr a0, mstatus + store_x a0, (128+128)(sp) + csrr a0, mcause + store_x a0, (132+132)(sp) + csrr a0, mtval + store_x a0, (136+136)(sp) + csrr a0, mscratch + store_x a0, ( 4 + 4 )(sp) +#else + addi sp, sp, -140 + store_x x1, ( 0 )(sp) + store_x x3, ( 8 )(sp) + store_x x4, ( 12)(sp) + store_x x5, ( 16)(sp) + store_x x6, ( 20)(sp) + store_x x7, ( 24)(sp) + store_x x8, ( 28)(sp) + store_x x9, ( 32)(sp) + store_x x10,( 36)(sp) + store_x x11,( 40)(sp) + store_x x12,( 44)(sp) + store_x x13,( 48)(sp) + store_x x14,( 52)(sp) + store_x x15,( 56)(sp) + store_x x16,( 60)(sp) + store_x x17,( 64)(sp) + store_x x18,( 68)(sp) + store_x x19,( 72)(sp) + store_x x20,( 76)(sp) + store_x x21,( 80)(sp) + store_x x22,( 84)(sp) + store_x x23,( 88)(sp) + store_x x24,( 92)(sp) + store_x x25,( 96)(sp) + store_x x26,(100)(sp) + store_x x27,(104)(sp) + store_x x28,(108)(sp) + store_x x29,(112)(sp) + store_x x30,(116)(sp) + store_x x31,(120)(sp) + csrr a0, mepc + store_x a0, (124)(sp) + csrr a0, mstatus + store_x a0, (128)(sp) + csrr a0, mcause + store_x a0, (132)(sp) + csrr a0, mtval + store_x a0, (136)(sp) + csrr a0, mscratch + store_x a0, ( 4 )(sp) +#endif + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/system.c new file mode 100644 index 00000000000..dfa4b9bfb9a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/system.c @@ -0,0 +1,316 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/vectors.S new file mode 100644 index 00000000000..317c7d4e93d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908/vectors.S @@ -0,0 +1,527 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/system.c new file mode 100644 index 00000000000..dfa4b9bfb9a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/system.c @@ -0,0 +1,316 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/vectors.S new file mode 100644 index 00000000000..317c7d4e93d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908i/vectors.S @@ -0,0 +1,527 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/system.c new file mode 100644 index 00000000000..dfa4b9bfb9a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/system.c @@ -0,0 +1,316 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/vectors.S new file mode 100644 index 00000000000..317c7d4e93d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c908v/vectors.S @@ -0,0 +1,527 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/system.c new file mode 100644 index 00000000000..dfa4b9bfb9a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/system.c @@ -0,0 +1,316 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/vectors.S new file mode 100644 index 00000000000..b49028d1903 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v2/vectors.S @@ -0,0 +1,521 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/system.c new file mode 100644 index 00000000000..8157f81729d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/system.c @@ -0,0 +1,324 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ +#if CONFIG_CPU_XUANTIE_C910V3_CP || CONFIG_CPU_XUANTIE_C920V3_CP + /* disable theadisaee & enable MM */ + unsigned long status = __get_MXSTATUS(); + status &= ~(1 << 22); + status |= (1 << 24 | 1 << 15); + __set_MXSTATUS(status); +#else + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); +#endif + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/vectors.S new file mode 100644 index 00000000000..b49028d1903 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3-cp/vectors.S @@ -0,0 +1,521 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/system.c new file mode 100644 index 00000000000..8157f81729d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/system.c @@ -0,0 +1,324 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ +#if CONFIG_CPU_XUANTIE_C910V3_CP || CONFIG_CPU_XUANTIE_C920V3_CP + /* disable theadisaee & enable MM */ + unsigned long status = __get_MXSTATUS(); + status &= ~(1 << 22); + status |= (1 << 24 | 1 << 15); + __set_MXSTATUS(status); +#else + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); +#endif + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/vectors.S new file mode 100644 index 00000000000..b49028d1903 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c910v3/vectors.S @@ -0,0 +1,521 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/system.c new file mode 100644 index 00000000000..dfa4b9bfb9a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/system.c @@ -0,0 +1,316 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/vectors.S new file mode 100644 index 00000000000..b49028d1903 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v2/vectors.S @@ -0,0 +1,521 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/system.c new file mode 100644 index 00000000000..8157f81729d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/system.c @@ -0,0 +1,324 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ +#if CONFIG_CPU_XUANTIE_C910V3_CP || CONFIG_CPU_XUANTIE_C920V3_CP + /* disable theadisaee & enable MM */ + unsigned long status = __get_MXSTATUS(); + status &= ~(1 << 22); + status |= (1 << 24 | 1 << 15); + __set_MXSTATUS(status); +#else + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); +#endif + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/vectors.S new file mode 100644 index 00000000000..b49028d1903 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3-cp/vectors.S @@ -0,0 +1,521 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/system.c new file mode 100644 index 00000000000..8157f81729d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/system.c @@ -0,0 +1,324 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ +#if CONFIG_CPU_XUANTIE_C910V3_CP || CONFIG_CPU_XUANTIE_C920V3_CP + /* disable theadisaee & enable MM */ + unsigned long status = __get_MXSTATUS(); + status &= ~(1 << 22); + status |= (1 << 24 | 1 << 15); + __set_MXSTATUS(status); +#else + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); +#endif + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/vectors.S new file mode 100644 index 00000000000..b49028d1903 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/c920v3/vectors.S @@ -0,0 +1,521 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/SConscript b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/SConscript new file mode 100644 index 00000000000..7c13ee46652 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/SConscript @@ -0,0 +1,13 @@ +from building import * +import os + +cwd = GetCurrentDir() +CPPPATH = [cwd] +src = ['startup.S'] +src += ['system.c'] +src += ['trap_c.c'] +src += ['vectors.S'] + +group = DefineGroup('sys', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/startup.S new file mode 100644 index 00000000000..c5d377905da --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/startup.S @@ -0,0 +1,135 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +.global __rt_rvstack +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal rtthread_startup + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 3 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +__rt_rvstack: +#ifdef CONFIG_KERNEL_NONE + .align 3 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/system.c new file mode 100644 index 00000000000..b4ed4130b52 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/system.c @@ -0,0 +1,100 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); +#endif + + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + csi_vic_set_prio(i, 1); + } + +#ifndef CONFIG_KERNEL_NONE + /* tspend use lower priority */ + csi_vic_set_prio(Machine_Software_IRQn, 0); + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +#endif +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22); + __set_MXSTATUS(status); + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/trap_c.c new file mode 100644 index 00000000000..78ae4585da0 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 15; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[15]); + printk("mstatus: %p\n", (void *)regs[16]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/vectors.S new file mode 100644 index 00000000000..48c6060a86e --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902/vectors.S @@ -0,0 +1,383 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 2 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, do_irq + jalr t0 + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + lw t0, 44(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -76 + sw x1, (0 )(sp) + sw x3, (8 )(sp) + sw x4, (12)(sp) + sw x5, (16)(sp) + sw x6, (20)(sp) + sw x7, (24)(sp) + sw x8, (28)(sp) + sw x9, (32)(sp) + sw x10,(36)(sp) + sw x11,(40)(sp) + sw x12,(44)(sp) + sw x13,(48)(sp) + sw x14,(52)(sp) + sw x15,(56)(sp) + csrr a0, mepc + sw a0, (60)(sp) + csrr a0, mstatus + sw a0, (64)(sp) + csrr a0, mcause + sw a0, (68)(sp) + csrr a0, mtval + sw a0, (72)(sp) + csrr a0, mscratch + sw a0, (4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, handle_nmi_exception + jalr t0 + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/startup.S new file mode 100644 index 00000000000..d092d3388c2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/startup.S @@ -0,0 +1,134 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 3 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 3 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/system.c new file mode 100644 index 00000000000..b4ed4130b52 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/system.c @@ -0,0 +1,100 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); +#endif + + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + csi_vic_set_prio(i, 1); + } + +#ifndef CONFIG_KERNEL_NONE + /* tspend use lower priority */ + csi_vic_set_prio(Machine_Software_IRQn, 0); + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +#endif +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22); + __set_MXSTATUS(status); + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/trap_c.c new file mode 100644 index 00000000000..78ae4585da0 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 15; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[15]); + printk("mstatus: %p\n", (void *)regs[16]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/vectors.S new file mode 100644 index 00000000000..48c6060a86e --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902m/vectors.S @@ -0,0 +1,383 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 2 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, do_irq + jalr t0 + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + lw t0, 44(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -76 + sw x1, (0 )(sp) + sw x3, (8 )(sp) + sw x4, (12)(sp) + sw x5, (16)(sp) + sw x6, (20)(sp) + sw x7, (24)(sp) + sw x8, (28)(sp) + sw x9, (32)(sp) + sw x10,(36)(sp) + sw x11,(40)(sp) + sw x12,(44)(sp) + sw x13,(48)(sp) + sw x14,(52)(sp) + sw x15,(56)(sp) + csrr a0, mepc + sw a0, (60)(sp) + csrr a0, mstatus + sw a0, (64)(sp) + csrr a0, mcause + sw a0, (68)(sp) + csrr a0, mtval + sw a0, (72)(sp) + csrr a0, mscratch + sw a0, (4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, handle_nmi_exception + jalr t0 + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/startup.S new file mode 100644 index 00000000000..d092d3388c2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/startup.S @@ -0,0 +1,134 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 3 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 3 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/system.c new file mode 100644 index 00000000000..b4ed4130b52 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/system.c @@ -0,0 +1,100 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); +#endif + + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + csi_vic_set_prio(i, 1); + } + +#ifndef CONFIG_KERNEL_NONE + /* tspend use lower priority */ + csi_vic_set_prio(Machine_Software_IRQn, 0); + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +#endif +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22); + __set_MXSTATUS(status); + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/trap_c.c new file mode 100644 index 00000000000..78ae4585da0 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 15; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[15]); + printk("mstatus: %p\n", (void *)regs[16]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/vectors.S new file mode 100644 index 00000000000..48c6060a86e --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902mt/vectors.S @@ -0,0 +1,383 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 2 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, do_irq + jalr t0 + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + lw t0, 44(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -76 + sw x1, (0 )(sp) + sw x3, (8 )(sp) + sw x4, (12)(sp) + sw x5, (16)(sp) + sw x6, (20)(sp) + sw x7, (24)(sp) + sw x8, (28)(sp) + sw x9, (32)(sp) + sw x10,(36)(sp) + sw x11,(40)(sp) + sw x12,(44)(sp) + sw x13,(48)(sp) + sw x14,(52)(sp) + sw x15,(56)(sp) + csrr a0, mepc + sw a0, (60)(sp) + csrr a0, mstatus + sw a0, (64)(sp) + csrr a0, mcause + sw a0, (68)(sp) + csrr a0, mtval + sw a0, (72)(sp) + csrr a0, mscratch + sw a0, (4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, handle_nmi_exception + jalr t0 + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/startup.S new file mode 100644 index 00000000000..d092d3388c2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/startup.S @@ -0,0 +1,134 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 3 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 3 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/system.c new file mode 100644 index 00000000000..b4ed4130b52 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/system.c @@ -0,0 +1,100 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); +#endif + + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + csi_vic_set_prio(i, 1); + } + +#ifndef CONFIG_KERNEL_NONE + /* tspend use lower priority */ + csi_vic_set_prio(Machine_Software_IRQn, 0); + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +#endif +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22); + __set_MXSTATUS(status); + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/trap_c.c new file mode 100644 index 00000000000..78ae4585da0 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 15; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[15]); + printk("mstatus: %p\n", (void *)regs[16]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/vectors.S new file mode 100644 index 00000000000..48c6060a86e --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e902t/vectors.S @@ -0,0 +1,383 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 2 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, do_irq + jalr t0 + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + lw t0, 44(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -76 + sw x1, (0 )(sp) + sw x3, (8 )(sp) + sw x4, (12)(sp) + sw x5, (16)(sp) + sw x6, (20)(sp) + sw x7, (24)(sp) + sw x8, (28)(sp) + sw x9, (32)(sp) + sw x10,(36)(sp) + sw x11,(40)(sp) + sw x12,(44)(sp) + sw x13,(48)(sp) + sw x14,(52)(sp) + sw x15,(56)(sp) + csrr a0, mepc + sw a0, (60)(sp) + csrr a0, mstatus + sw a0, (64)(sp) + csrr a0, mcause + sw a0, (68)(sp) + csrr a0, mtval + sw a0, (72)(sp) + csrr a0, mscratch + sw a0, (4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -48 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 40(sp) + sw t0, 44(sp) + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + + la t0, handle_nmi_exception + jalr t0 + + lw a1, 40(sp) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + lw t0, 44(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + + addi sp, sp, 48 + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/SConscript b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/SConscript new file mode 100644 index 00000000000..7c13ee46652 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/SConscript @@ -0,0 +1,13 @@ +from building import * +import os + +cwd = GetCurrentDir() +CPPPATH = [cwd] +src = ['startup.S'] +src += ['system.c'] +src += ['trap_c.c'] +src += ['vectors.S'] + +group = DefineGroup('sys', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/startup.S new file mode 100644 index 00000000000..82174509466 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/startup.S @@ -0,0 +1,170 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.global __rt_rvstack +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal rtthread_startup + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +__rt_rvstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/system.c new file mode 100644 index 00000000000..0b8939890d7 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(10000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/vectors.S new file mode 100644 index 00000000000..6bb2e9836c3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906/vectors.S @@ -0,0 +1,591 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 +#if CONFIG_CHECK_FPU_DIRTY + lw t0, 72(sp) + csrw mstatus, t0 +#endif + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/startup.S new file mode 100644 index 00000000000..65032fbbb7c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/startup.S @@ -0,0 +1,168 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/system.c new file mode 100644 index 00000000000..904523c669f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/vectors.S new file mode 100644 index 00000000000..6bb2e9836c3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906f/vectors.S @@ -0,0 +1,591 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 +#if CONFIG_CHECK_FPU_DIRTY + lw t0, 72(sp) + csrw mstatus, t0 +#endif + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/SConscript b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/SConscript new file mode 100644 index 00000000000..7c13ee46652 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/SConscript @@ -0,0 +1,13 @@ +from building import * +import os + +cwd = GetCurrentDir() +CPPPATH = [cwd] +src = ['startup.S'] +src += ['system.c'] +src += ['trap_c.c'] +src += ['vectors.S'] + +group = DefineGroup('sys', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/startup.S new file mode 100644 index 00000000000..8843b34fb0d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/startup.S @@ -0,0 +1,169 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +.global __rt_rvstack +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal rtthread_startup + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +__rt_rvstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/system.c new file mode 100644 index 00000000000..904523c669f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/vectors.S new file mode 100644 index 00000000000..6bb2e9836c3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fd/vectors.S @@ -0,0 +1,591 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 +#if CONFIG_CHECK_FPU_DIRTY + lw t0, 72(sp) + csrw mstatus, t0 +#endif + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/startup.S new file mode 100644 index 00000000000..65032fbbb7c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/startup.S @@ -0,0 +1,168 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/system.c new file mode 100644 index 00000000000..904523c669f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/vectors.S new file mode 100644 index 00000000000..6bb2e9836c3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fdp/vectors.S @@ -0,0 +1,591 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 +#if CONFIG_CHECK_FPU_DIRTY + lw t0, 72(sp) + csrw mstatus, t0 +#endif + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/startup.S new file mode 100644 index 00000000000..65032fbbb7c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/startup.S @@ -0,0 +1,168 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/system.c new file mode 100644 index 00000000000..904523c669f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/vectors.S new file mode 100644 index 00000000000..6bb2e9836c3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906fp/vectors.S @@ -0,0 +1,591 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 +#if CONFIG_CHECK_FPU_DIRTY + lw t0, 72(sp) + csrw mstatus, t0 +#endif + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/startup.S new file mode 100644 index 00000000000..65032fbbb7c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/startup.S @@ -0,0 +1,168 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/system.c new file mode 100644 index 00000000000..904523c669f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/vectors.S new file mode 100644 index 00000000000..6bb2e9836c3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e906p/vectors.S @@ -0,0 +1,591 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 +#if CONFIG_CHECK_FPU_DIRTY + lw t0, 72(sp) + csrw mstatus, t0 +#endif + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/SConscript b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/SConscript new file mode 100644 index 00000000000..7c13ee46652 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/SConscript @@ -0,0 +1,13 @@ +from building import * +import os + +cwd = GetCurrentDir() +CPPPATH = [cwd] +src = ['startup.S'] +src += ['system.c'] +src += ['trap_c.c'] +src += ['vectors.S'] + +group = DefineGroup('sys', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/startup.S new file mode 100644 index 00000000000..8116bc5f4a1 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/startup.S @@ -0,0 +1,173 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +.global __rt_rvstack +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler +#if CONFIG_IRQ_LATENCY + .long IRQ_LATENCY_IRQHandler +#else + .long Default_IRQHandler +#endif + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal rtthread_startup + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +__rt_rvstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/system.c new file mode 100644 index 00000000000..904523c669f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/vectors.S new file mode 100644 index 00000000000..d1f896319f4 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907/vectors.S @@ -0,0 +1,588 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/startup.S new file mode 100644 index 00000000000..b65fed1ed5c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/startup.S @@ -0,0 +1,172 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler +#if CONFIG_IRQ_LATENCY + .long IRQ_LATENCY_IRQHandler +#else + .long Default_IRQHandler +#endif + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/system.c new file mode 100644 index 00000000000..904523c669f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/vectors.S new file mode 100644 index 00000000000..d1f896319f4 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907f/vectors.S @@ -0,0 +1,588 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/startup.S new file mode 100644 index 00000000000..b65fed1ed5c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/startup.S @@ -0,0 +1,172 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler +#if CONFIG_IRQ_LATENCY + .long IRQ_LATENCY_IRQHandler +#else + .long Default_IRQHandler +#endif + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/system.c new file mode 100644 index 00000000000..904523c669f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/vectors.S new file mode 100644 index 00000000000..d1f896319f4 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fd/vectors.S @@ -0,0 +1,588 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/startup.S new file mode 100644 index 00000000000..b65fed1ed5c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/startup.S @@ -0,0 +1,172 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler +#if CONFIG_IRQ_LATENCY + .long IRQ_LATENCY_IRQHandler +#else + .long Default_IRQHandler +#endif + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/system.c new file mode 100644 index 00000000000..904523c669f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/vectors.S new file mode 100644 index 00000000000..d1f896319f4 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fdp/vectors.S @@ -0,0 +1,588 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/startup.S new file mode 100644 index 00000000000..b65fed1ed5c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/startup.S @@ -0,0 +1,172 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler +#if CONFIG_IRQ_LATENCY + .long IRQ_LATENCY_IRQHandler +#else + .long Default_IRQHandler +#endif + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/system.c new file mode 100644 index 00000000000..904523c669f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/vectors.S new file mode 100644 index 00000000000..d1f896319f4 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907fp/vectors.S @@ -0,0 +1,588 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/startup.S new file mode 100644 index 00000000000..b65fed1ed5c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/startup.S @@ -0,0 +1,172 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long tspend_handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_IRQHandler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + .long Default_Handler + + /* External interrupts */ + .long Default_IRQHandler +#if CONFIG_IRQ_LATENCY + .long IRQ_LATENCY_IRQHandler +#else + .long Default_IRQHandler +#endif + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + .long Default_IRQHandler + + .size __Vectors, . - __Vectors + + .globl Reset_Handler + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .long Reset_Handler + .align 2 + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + la gp, __global_pointer$ +.option pop + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 + + la sp, g_top_irqstack + csrw mscratch, sp +#ifdef CONFIG_KERNEL_NONE + la sp, g_top_mainstack +#endif + +#ifndef __NO_SYSTEM_INIT + jal SystemInit +#endif + + jal pre_main + + .size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_irqstack: +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK +g_top_mainstack: +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/system.c new file mode 100644 index 00000000000..904523c669f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/system.c @@ -0,0 +1,113 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +static void cache_init(void) +{ + csi_dcache_enable(); + csi_icache_enable(); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + section_bss_clear(); +} + +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); +} + +static void interrupt_init(void) +{ + clic_init(); +#ifdef CONFIG_KERNEL_NONE + __enable_excp_irq(); +#endif +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + uint32_t status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif + /* enable mexstatus SPUSHEN and disable SPSWAPEN */ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + status = __get_MEXSTATUS(); + status |= (0x1 << 16); + status &= ~(0x2 << 16); + __set_MEXSTATUS(status); +#endif + + cache_init(); + section_init(); + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/vectors.S new file mode 100644 index 00000000000..d1f896319f4 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/e907p/vectors.S @@ -0,0 +1,588 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) +.section .bss +irq_nested_level: +.long 0 + +irq_nested_mcause: +.long 0, 0, 0, 0, 0, 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + csrw mscratch, sp + la sp, g_top_irqstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret +#else + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -8 + sw t0, 0(sp) + sw t1, 4(sp) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, 1 + sw t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t0, t0, t1 + csrr t1, mcause + sw t1, (t0) + + la t0, irq_nested_level + lw t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + + csrw mscratch, sp + la sp, g_top_irqstack + j .Lnested2 +.Lnested1: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + csrs mstatus, 8 + + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + slli t1, t1, 2 + add t1, t0, t1 + lw t0, (t1) + andi t0, t0, 0x3FF + andi a0, a1, 0xFFFFFC00 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + mret +#endif + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 2 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -140 + sw x1, ( 0 )(sp) + sw x3, ( 8 )(sp) + sw x4, ( 12)(sp) + sw x5, ( 16)(sp) + sw x6, ( 20)(sp) + sw x7, ( 24)(sp) + sw x8, ( 28)(sp) + sw x9, ( 32)(sp) + sw x10,( 36)(sp) + sw x11,( 40)(sp) + sw x12,( 44)(sp) + sw x13,( 48)(sp) + sw x14,( 52)(sp) + sw x15,( 56)(sp) + sw x16,( 60)(sp) + sw x17,( 64)(sp) + sw x18,( 68)(sp) + sw x19,( 72)(sp) + sw x20,( 76)(sp) + sw x21,( 80)(sp) + sw x22,( 84)(sp) + sw x23,( 88)(sp) + sw x24,( 92)(sp) + sw x25,( 96)(sp) + sw x26,(100)(sp) + sw x27,(104)(sp) + sw x28,(108)(sp) + sw x29,(112)(sp) + sw x30,(116)(sp) + sw x31,(120)(sp) + csrr a0, mepc + sw a0, (124)(sp) + csrr a0, mstatus + sw a0, (128)(sp) + csrr a0, mcause + sw a0, (132)(sp) + csrr a0, mtval + sw a0, (136)(sp) + csrr a0, mscratch + sw a0, ( 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + /* Check for nmi */ + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + csrr t0, mcause + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + j trap +.NMI_Handler: + /* mscratch may be used before */ + addi sp, sp, -4 + csrr t0, mscratch + sw t0, 0x0(sp) + + csrw mscratch, sp + la sp, g_top_trapstack +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, -76 +#else + addi sp, sp, -72 +#endif + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + +#if CONFIG_CHECK_FPU_DIRTY + csrr t0, mstatus + sw t0, 72(sp) +#endif + sw ra, 0(sp) + sw t2, 12(sp) + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + sw a4, 32(sp) + sw a5, 36(sp) + sw a6, 40(sp) + sw a7, 44(sp) + sw t3, 48(sp) + sw t4, 52(sp) + sw t5, 56(sp) + sw t6, 60(sp) + +#if __riscv_dsp + addi sp, sp, -4 + csrr t0, vxsat + sw t0, 0(sp) +#endif /*__riscv_dsp */ + +#if CONFIG_CHECK_FPU_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + + la t0, handle_nmi_exception + jalr t0 + + /* get mcause from sp */ + addi t0, sp, 64 +#if __riscv_dsp + addi t0, t0, 4 +#endif /*__riscv_dsp */ +#if __riscv_flen == 64 + addi t0, t0, 164 +#elif __riscv_flen == 32 + addi t0, t0, 84 +#endif + lw a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clear pending */ + li a2, 0xE0801000 + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw t0, 68(sp) + csrw mepc, t0 + lw ra, 0(sp) + lw t0, 4(sp) + lw t1, 8(sp) + lw t2, 12(sp) + lw a0, 16(sp) + lw a1, 20(sp) + lw a2, 24(sp) + lw a3, 28(sp) + lw a4, 32(sp) + lw a5, 36(sp) + lw a6, 40(sp) + lw a7, 44(sp) + lw t3, 48(sp) + lw t4, 52(sp) + lw t5, 56(sp) + lw t6, 60(sp) + +#if CONFIG_CHECK_FPU_DIRTY + addi sp, sp, 76 +#else + addi sp, sp, 72 +#endif + csrr sp, mscratch + + /* restore mscratch */ + lw t0, 0x0(sp) + csrw mscratch, t0 + addi sp, sp, 4 + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + mret + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/startup.S new file mode 100644 index 00000000000..f6cd7865859 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/startup.S @@ -0,0 +1,292 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: +#if CONFIG_INTC_CLIC_PLIC + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword tspend_handler /* 3 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Mcoret_Handler /* 7 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_IRQHandler /* 11 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + + /* External interrupts */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + .dword ECC_L1_Handler /* 16 */ +#else + .dword Default_IRQHandler /* 16 */ +#endif +#if CONFIG_IRQ_LATENCY + .dword IRQ_LATENCY_IRQHandler +#else + .dword Default_IRQHandler +#endif + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler +#else + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif +#endif + + .size __Vectors, . - __Vectors + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop +#if CONFIG_INTC_CLIC_PLIC + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 +#else + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 +#endif + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/system.c new file mode 100644 index 00000000000..6b9b5b4d028 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/system.c @@ -0,0 +1,406 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if !CONFIG_INTC_CLIC_PLIC && CONFIG_SUPPORT_IRQ_NESTED +#error "Please disable CONFIG_SUPPORT_IRQ_NESTED in package.yaml when use PLIC." +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void fpp_init(void) +{ +#if CONFIG_FPP_ENABLE + csi_fpp_set_base_addr(0x19000000); + csi_fpp_enable(); +#endif +} + +#if CONFIG_INTC_CLIC_PLIC +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + CLIC->CLICINT[i].CTL = (CLIC->CLICINT[i].CTL & (~CLIC_INTCFG_PRIO_Msk)) | (0x1 << (8 - nlbits)); + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); + + /* enable external plic interrupt */ + csi_irq_enable(Machine_External_IRQn); + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + CLIC->CLICINT[L1_CACHE_ECC_IRQn].ATTR = 0x3; + csi_irq_enable(L1_CACHE_ECC_IRQn); +#endif +} +#endif + +static void interrupt_init(void) +{ + int i; + +#if CONFIG_INTC_CLIC_PLIC + clic_init(); + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; +#else + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +#endif +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ +#if CONFIG_CPU_XUANTIE_R908_CP || CONFIG_CPU_XUANTIE_R908FD_CP || CONFIG_CPU_XUANTIE_R908FDV_CP + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status &= ~(1 << 22); + status |= (1 << 24 | 1 << 15); + __set_MXSTATUS(status); +#else + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); +#endif + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#if CONFIG_ECC_ITCM_ENABLE + uint64_t mitcmcr = __get_MITCMCR(); + mitcmcr |= MITCMCR_ECC_EN_Msk; + __set_MITCMCR(mitcmcr); +#endif + +#if CONFIG_ECC_DTCM_ENABLE + uint64_t mdtcmcr = __get_MDTCMCR(); + mdtcmcr |= MDTCMCR_ECC_EN_Msk; + __set_MDTCMCR(mdtcmcr); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + fpp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/vectors.S new file mode 100644 index 00000000000..e5417cc677a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908-cp/vectors.S @@ -0,0 +1,983 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_INTC_CLIC_PLIC + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) + +.section .bss +.align 3 +.global irq_nested_level +irq_nested_level: + .space 8 * CONFIG_NR_CPUS +irq_nested_level_end: + +irq_nested_mcause: + .space 8 * CONFIG_NR_CPUS * IRQ_NESTED_MAX +irq_nested_mcause_end: +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + sd ra, (0)(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrr a1, mcause + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, (0)(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#else /* CONFIG_SUPPORT_IRQ_NESTED */ + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -(8+8+8+8) + sd t0, 0(sp) + sd t1, (4+4)(sp) + sd t2, (8+8)(sp) + sd t3, (12+12)(sp) + + csrr t3, mhartid + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, 1 + sd t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + csrr t1, mcause + sd t1, (t0) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -16 + sd s0, (sp) + csrr t0, mepc + sd t0, 8(sp) +#endif + csrw mscratch, sp + la sp, g_base_irqstack + addi t1, t3, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + j .Lnested2 +.Lnested1: + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + csrs mstatus, 8 + + sd ra, 0(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from irq_nested_mcause */ + csrr t3, mhartid + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + ld a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + sd t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 16 +#endif + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + mv t1, t0 + + ld t0, (t1) + andi t0, t0, 0x3FF + srli a0, a1, 11 + slli a0, a0, 11 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + mret +#endif /* CONFIG_SUPPORT_IRQ_NESTED */ + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + j Default_IRQHandler + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 )(sp) + sd x3, ( 8+8)(sp) + sd x4, ( 12+12)(sp) + sd x5, ( 16+16)(sp) + sd x6, ( 20+20)(sp) + sd x7, ( 24+24)(sp) + sd x8, ( 28+28)(sp) + sd x9, ( 32+32)(sp) + sd x10,( 36+36)(sp) + sd x11,( 40+40)(sp) + sd x12,( 44+44)(sp) + sd x13,( 48+48)(sp) + sd x14,( 52+52)(sp) + sd x15,( 56+56)(sp) + sd x16,( 60+60)(sp) + sd x17,( 64+64)(sp) + sd x18,( 68+68)(sp) + sd x19,( 72+72)(sp) + sd x20,( 76+76)(sp) + sd x21,( 80+80)(sp) + sd x22,( 84+84)(sp) + sd x23,( 88+88)(sp) + sd x24,( 92+92)(sp) + sd x25,( 96+96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4+4)(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler + +#else /* !CONFIG_INTC_CLIC_PLIC */ + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler +#endif + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE +.text + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .size ECC_L1_Handler, . - ECC_L1_Handler +#endif /* CONFIG_INTC_CLIC_PLIC */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/startup.S new file mode 100644 index 00000000000..f6cd7865859 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/startup.S @@ -0,0 +1,292 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: +#if CONFIG_INTC_CLIC_PLIC + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword tspend_handler /* 3 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Mcoret_Handler /* 7 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_IRQHandler /* 11 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + + /* External interrupts */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + .dword ECC_L1_Handler /* 16 */ +#else + .dword Default_IRQHandler /* 16 */ +#endif +#if CONFIG_IRQ_LATENCY + .dword IRQ_LATENCY_IRQHandler +#else + .dword Default_IRQHandler +#endif + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler +#else + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif +#endif + + .size __Vectors, . - __Vectors + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop +#if CONFIG_INTC_CLIC_PLIC + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 +#else + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 +#endif + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/system.c new file mode 100644 index 00000000000..6b9b5b4d028 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/system.c @@ -0,0 +1,406 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if !CONFIG_INTC_CLIC_PLIC && CONFIG_SUPPORT_IRQ_NESTED +#error "Please disable CONFIG_SUPPORT_IRQ_NESTED in package.yaml when use PLIC." +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void fpp_init(void) +{ +#if CONFIG_FPP_ENABLE + csi_fpp_set_base_addr(0x19000000); + csi_fpp_enable(); +#endif +} + +#if CONFIG_INTC_CLIC_PLIC +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + CLIC->CLICINT[i].CTL = (CLIC->CLICINT[i].CTL & (~CLIC_INTCFG_PRIO_Msk)) | (0x1 << (8 - nlbits)); + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); + + /* enable external plic interrupt */ + csi_irq_enable(Machine_External_IRQn); + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + CLIC->CLICINT[L1_CACHE_ECC_IRQn].ATTR = 0x3; + csi_irq_enable(L1_CACHE_ECC_IRQn); +#endif +} +#endif + +static void interrupt_init(void) +{ + int i; + +#if CONFIG_INTC_CLIC_PLIC + clic_init(); + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; +#else + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +#endif +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ +#if CONFIG_CPU_XUANTIE_R908_CP || CONFIG_CPU_XUANTIE_R908FD_CP || CONFIG_CPU_XUANTIE_R908FDV_CP + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status &= ~(1 << 22); + status |= (1 << 24 | 1 << 15); + __set_MXSTATUS(status); +#else + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); +#endif + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#if CONFIG_ECC_ITCM_ENABLE + uint64_t mitcmcr = __get_MITCMCR(); + mitcmcr |= MITCMCR_ECC_EN_Msk; + __set_MITCMCR(mitcmcr); +#endif + +#if CONFIG_ECC_DTCM_ENABLE + uint64_t mdtcmcr = __get_MDTCMCR(); + mdtcmcr |= MDTCMCR_ECC_EN_Msk; + __set_MDTCMCR(mdtcmcr); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + fpp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/vectors.S new file mode 100644 index 00000000000..e5417cc677a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908/vectors.S @@ -0,0 +1,983 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_INTC_CLIC_PLIC + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) + +.section .bss +.align 3 +.global irq_nested_level +irq_nested_level: + .space 8 * CONFIG_NR_CPUS +irq_nested_level_end: + +irq_nested_mcause: + .space 8 * CONFIG_NR_CPUS * IRQ_NESTED_MAX +irq_nested_mcause_end: +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + sd ra, (0)(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrr a1, mcause + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, (0)(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#else /* CONFIG_SUPPORT_IRQ_NESTED */ + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -(8+8+8+8) + sd t0, 0(sp) + sd t1, (4+4)(sp) + sd t2, (8+8)(sp) + sd t3, (12+12)(sp) + + csrr t3, mhartid + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, 1 + sd t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + csrr t1, mcause + sd t1, (t0) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -16 + sd s0, (sp) + csrr t0, mepc + sd t0, 8(sp) +#endif + csrw mscratch, sp + la sp, g_base_irqstack + addi t1, t3, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + j .Lnested2 +.Lnested1: + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + csrs mstatus, 8 + + sd ra, 0(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from irq_nested_mcause */ + csrr t3, mhartid + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + ld a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + sd t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 16 +#endif + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + mv t1, t0 + + ld t0, (t1) + andi t0, t0, 0x3FF + srli a0, a1, 11 + slli a0, a0, 11 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + mret +#endif /* CONFIG_SUPPORT_IRQ_NESTED */ + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + j Default_IRQHandler + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 )(sp) + sd x3, ( 8+8)(sp) + sd x4, ( 12+12)(sp) + sd x5, ( 16+16)(sp) + sd x6, ( 20+20)(sp) + sd x7, ( 24+24)(sp) + sd x8, ( 28+28)(sp) + sd x9, ( 32+32)(sp) + sd x10,( 36+36)(sp) + sd x11,( 40+40)(sp) + sd x12,( 44+44)(sp) + sd x13,( 48+48)(sp) + sd x14,( 52+52)(sp) + sd x15,( 56+56)(sp) + sd x16,( 60+60)(sp) + sd x17,( 64+64)(sp) + sd x18,( 68+68)(sp) + sd x19,( 72+72)(sp) + sd x20,( 76+76)(sp) + sd x21,( 80+80)(sp) + sd x22,( 84+84)(sp) + sd x23,( 88+88)(sp) + sd x24,( 92+92)(sp) + sd x25,( 96+96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4+4)(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler + +#else /* !CONFIG_INTC_CLIC_PLIC */ + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler +#endif + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE +.text + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .size ECC_L1_Handler, . - ECC_L1_Handler +#endif /* CONFIG_INTC_CLIC_PLIC */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/startup.S new file mode 100644 index 00000000000..f6cd7865859 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/startup.S @@ -0,0 +1,292 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: +#if CONFIG_INTC_CLIC_PLIC + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword tspend_handler /* 3 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Mcoret_Handler /* 7 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_IRQHandler /* 11 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + + /* External interrupts */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + .dword ECC_L1_Handler /* 16 */ +#else + .dword Default_IRQHandler /* 16 */ +#endif +#if CONFIG_IRQ_LATENCY + .dword IRQ_LATENCY_IRQHandler +#else + .dword Default_IRQHandler +#endif + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler +#else + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif +#endif + + .size __Vectors, . - __Vectors + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop +#if CONFIG_INTC_CLIC_PLIC + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 +#else + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 +#endif + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/system.c new file mode 100644 index 00000000000..6b9b5b4d028 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/system.c @@ -0,0 +1,406 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if !CONFIG_INTC_CLIC_PLIC && CONFIG_SUPPORT_IRQ_NESTED +#error "Please disable CONFIG_SUPPORT_IRQ_NESTED in package.yaml when use PLIC." +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void fpp_init(void) +{ +#if CONFIG_FPP_ENABLE + csi_fpp_set_base_addr(0x19000000); + csi_fpp_enable(); +#endif +} + +#if CONFIG_INTC_CLIC_PLIC +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + CLIC->CLICINT[i].CTL = (CLIC->CLICINT[i].CTL & (~CLIC_INTCFG_PRIO_Msk)) | (0x1 << (8 - nlbits)); + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); + + /* enable external plic interrupt */ + csi_irq_enable(Machine_External_IRQn); + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + CLIC->CLICINT[L1_CACHE_ECC_IRQn].ATTR = 0x3; + csi_irq_enable(L1_CACHE_ECC_IRQn); +#endif +} +#endif + +static void interrupt_init(void) +{ + int i; + +#if CONFIG_INTC_CLIC_PLIC + clic_init(); + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; +#else + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +#endif +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ +#if CONFIG_CPU_XUANTIE_R908_CP || CONFIG_CPU_XUANTIE_R908FD_CP || CONFIG_CPU_XUANTIE_R908FDV_CP + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status &= ~(1 << 22); + status |= (1 << 24 | 1 << 15); + __set_MXSTATUS(status); +#else + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); +#endif + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#if CONFIG_ECC_ITCM_ENABLE + uint64_t mitcmcr = __get_MITCMCR(); + mitcmcr |= MITCMCR_ECC_EN_Msk; + __set_MITCMCR(mitcmcr); +#endif + +#if CONFIG_ECC_DTCM_ENABLE + uint64_t mdtcmcr = __get_MDTCMCR(); + mdtcmcr |= MDTCMCR_ECC_EN_Msk; + __set_MDTCMCR(mdtcmcr); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + fpp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/vectors.S new file mode 100644 index 00000000000..e5417cc677a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd-cp/vectors.S @@ -0,0 +1,983 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_INTC_CLIC_PLIC + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) + +.section .bss +.align 3 +.global irq_nested_level +irq_nested_level: + .space 8 * CONFIG_NR_CPUS +irq_nested_level_end: + +irq_nested_mcause: + .space 8 * CONFIG_NR_CPUS * IRQ_NESTED_MAX +irq_nested_mcause_end: +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + sd ra, (0)(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrr a1, mcause + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, (0)(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#else /* CONFIG_SUPPORT_IRQ_NESTED */ + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -(8+8+8+8) + sd t0, 0(sp) + sd t1, (4+4)(sp) + sd t2, (8+8)(sp) + sd t3, (12+12)(sp) + + csrr t3, mhartid + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, 1 + sd t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + csrr t1, mcause + sd t1, (t0) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -16 + sd s0, (sp) + csrr t0, mepc + sd t0, 8(sp) +#endif + csrw mscratch, sp + la sp, g_base_irqstack + addi t1, t3, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + j .Lnested2 +.Lnested1: + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + csrs mstatus, 8 + + sd ra, 0(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from irq_nested_mcause */ + csrr t3, mhartid + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + ld a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + sd t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 16 +#endif + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + mv t1, t0 + + ld t0, (t1) + andi t0, t0, 0x3FF + srli a0, a1, 11 + slli a0, a0, 11 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + mret +#endif /* CONFIG_SUPPORT_IRQ_NESTED */ + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + j Default_IRQHandler + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 )(sp) + sd x3, ( 8+8)(sp) + sd x4, ( 12+12)(sp) + sd x5, ( 16+16)(sp) + sd x6, ( 20+20)(sp) + sd x7, ( 24+24)(sp) + sd x8, ( 28+28)(sp) + sd x9, ( 32+32)(sp) + sd x10,( 36+36)(sp) + sd x11,( 40+40)(sp) + sd x12,( 44+44)(sp) + sd x13,( 48+48)(sp) + sd x14,( 52+52)(sp) + sd x15,( 56+56)(sp) + sd x16,( 60+60)(sp) + sd x17,( 64+64)(sp) + sd x18,( 68+68)(sp) + sd x19,( 72+72)(sp) + sd x20,( 76+76)(sp) + sd x21,( 80+80)(sp) + sd x22,( 84+84)(sp) + sd x23,( 88+88)(sp) + sd x24,( 92+92)(sp) + sd x25,( 96+96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4+4)(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler + +#else /* !CONFIG_INTC_CLIC_PLIC */ + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler +#endif + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE +.text + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .size ECC_L1_Handler, . - ECC_L1_Handler +#endif /* CONFIG_INTC_CLIC_PLIC */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/startup.S new file mode 100644 index 00000000000..f6cd7865859 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/startup.S @@ -0,0 +1,292 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: +#if CONFIG_INTC_CLIC_PLIC + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword tspend_handler /* 3 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Mcoret_Handler /* 7 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_IRQHandler /* 11 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + + /* External interrupts */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + .dword ECC_L1_Handler /* 16 */ +#else + .dword Default_IRQHandler /* 16 */ +#endif +#if CONFIG_IRQ_LATENCY + .dword IRQ_LATENCY_IRQHandler +#else + .dword Default_IRQHandler +#endif + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler +#else + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif +#endif + + .size __Vectors, . - __Vectors + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop +#if CONFIG_INTC_CLIC_PLIC + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 +#else + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 +#endif + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/system.c new file mode 100644 index 00000000000..6b9b5b4d028 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/system.c @@ -0,0 +1,406 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if !CONFIG_INTC_CLIC_PLIC && CONFIG_SUPPORT_IRQ_NESTED +#error "Please disable CONFIG_SUPPORT_IRQ_NESTED in package.yaml when use PLIC." +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void fpp_init(void) +{ +#if CONFIG_FPP_ENABLE + csi_fpp_set_base_addr(0x19000000); + csi_fpp_enable(); +#endif +} + +#if CONFIG_INTC_CLIC_PLIC +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + CLIC->CLICINT[i].CTL = (CLIC->CLICINT[i].CTL & (~CLIC_INTCFG_PRIO_Msk)) | (0x1 << (8 - nlbits)); + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); + + /* enable external plic interrupt */ + csi_irq_enable(Machine_External_IRQn); + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + CLIC->CLICINT[L1_CACHE_ECC_IRQn].ATTR = 0x3; + csi_irq_enable(L1_CACHE_ECC_IRQn); +#endif +} +#endif + +static void interrupt_init(void) +{ + int i; + +#if CONFIG_INTC_CLIC_PLIC + clic_init(); + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; +#else + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +#endif +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ +#if CONFIG_CPU_XUANTIE_R908_CP || CONFIG_CPU_XUANTIE_R908FD_CP || CONFIG_CPU_XUANTIE_R908FDV_CP + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status &= ~(1 << 22); + status |= (1 << 24 | 1 << 15); + __set_MXSTATUS(status); +#else + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); +#endif + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#if CONFIG_ECC_ITCM_ENABLE + uint64_t mitcmcr = __get_MITCMCR(); + mitcmcr |= MITCMCR_ECC_EN_Msk; + __set_MITCMCR(mitcmcr); +#endif + +#if CONFIG_ECC_DTCM_ENABLE + uint64_t mdtcmcr = __get_MDTCMCR(); + mdtcmcr |= MDTCMCR_ECC_EN_Msk; + __set_MDTCMCR(mdtcmcr); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + fpp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/vectors.S new file mode 100644 index 00000000000..e5417cc677a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fd/vectors.S @@ -0,0 +1,983 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_INTC_CLIC_PLIC + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) + +.section .bss +.align 3 +.global irq_nested_level +irq_nested_level: + .space 8 * CONFIG_NR_CPUS +irq_nested_level_end: + +irq_nested_mcause: + .space 8 * CONFIG_NR_CPUS * IRQ_NESTED_MAX +irq_nested_mcause_end: +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + sd ra, (0)(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrr a1, mcause + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, (0)(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#else /* CONFIG_SUPPORT_IRQ_NESTED */ + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -(8+8+8+8) + sd t0, 0(sp) + sd t1, (4+4)(sp) + sd t2, (8+8)(sp) + sd t3, (12+12)(sp) + + csrr t3, mhartid + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, 1 + sd t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + csrr t1, mcause + sd t1, (t0) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -16 + sd s0, (sp) + csrr t0, mepc + sd t0, 8(sp) +#endif + csrw mscratch, sp + la sp, g_base_irqstack + addi t1, t3, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + j .Lnested2 +.Lnested1: + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + csrs mstatus, 8 + + sd ra, 0(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from irq_nested_mcause */ + csrr t3, mhartid + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + ld a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + sd t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 16 +#endif + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + mv t1, t0 + + ld t0, (t1) + andi t0, t0, 0x3FF + srli a0, a1, 11 + slli a0, a0, 11 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + mret +#endif /* CONFIG_SUPPORT_IRQ_NESTED */ + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + j Default_IRQHandler + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 )(sp) + sd x3, ( 8+8)(sp) + sd x4, ( 12+12)(sp) + sd x5, ( 16+16)(sp) + sd x6, ( 20+20)(sp) + sd x7, ( 24+24)(sp) + sd x8, ( 28+28)(sp) + sd x9, ( 32+32)(sp) + sd x10,( 36+36)(sp) + sd x11,( 40+40)(sp) + sd x12,( 44+44)(sp) + sd x13,( 48+48)(sp) + sd x14,( 52+52)(sp) + sd x15,( 56+56)(sp) + sd x16,( 60+60)(sp) + sd x17,( 64+64)(sp) + sd x18,( 68+68)(sp) + sd x19,( 72+72)(sp) + sd x20,( 76+76)(sp) + sd x21,( 80+80)(sp) + sd x22,( 84+84)(sp) + sd x23,( 88+88)(sp) + sd x24,( 92+92)(sp) + sd x25,( 96+96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4+4)(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler + +#else /* !CONFIG_INTC_CLIC_PLIC */ + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler +#endif + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE +.text + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .size ECC_L1_Handler, . - ECC_L1_Handler +#endif /* CONFIG_INTC_CLIC_PLIC */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/startup.S new file mode 100644 index 00000000000..f6cd7865859 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/startup.S @@ -0,0 +1,292 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: +#if CONFIG_INTC_CLIC_PLIC + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword tspend_handler /* 3 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Mcoret_Handler /* 7 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_IRQHandler /* 11 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + + /* External interrupts */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + .dword ECC_L1_Handler /* 16 */ +#else + .dword Default_IRQHandler /* 16 */ +#endif +#if CONFIG_IRQ_LATENCY + .dword IRQ_LATENCY_IRQHandler +#else + .dword Default_IRQHandler +#endif + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler +#else + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif +#endif + + .size __Vectors, . - __Vectors + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop +#if CONFIG_INTC_CLIC_PLIC + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 +#else + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 +#endif + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/system.c new file mode 100644 index 00000000000..6b9b5b4d028 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/system.c @@ -0,0 +1,406 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if !CONFIG_INTC_CLIC_PLIC && CONFIG_SUPPORT_IRQ_NESTED +#error "Please disable CONFIG_SUPPORT_IRQ_NESTED in package.yaml when use PLIC." +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void fpp_init(void) +{ +#if CONFIG_FPP_ENABLE + csi_fpp_set_base_addr(0x19000000); + csi_fpp_enable(); +#endif +} + +#if CONFIG_INTC_CLIC_PLIC +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + CLIC->CLICINT[i].CTL = (CLIC->CLICINT[i].CTL & (~CLIC_INTCFG_PRIO_Msk)) | (0x1 << (8 - nlbits)); + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); + + /* enable external plic interrupt */ + csi_irq_enable(Machine_External_IRQn); + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + CLIC->CLICINT[L1_CACHE_ECC_IRQn].ATTR = 0x3; + csi_irq_enable(L1_CACHE_ECC_IRQn); +#endif +} +#endif + +static void interrupt_init(void) +{ + int i; + +#if CONFIG_INTC_CLIC_PLIC + clic_init(); + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; +#else + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +#endif +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ +#if CONFIG_CPU_XUANTIE_R908_CP || CONFIG_CPU_XUANTIE_R908FD_CP || CONFIG_CPU_XUANTIE_R908FDV_CP + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status &= ~(1 << 22); + status |= (1 << 24 | 1 << 15); + __set_MXSTATUS(status); +#else + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); +#endif + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#if CONFIG_ECC_ITCM_ENABLE + uint64_t mitcmcr = __get_MITCMCR(); + mitcmcr |= MITCMCR_ECC_EN_Msk; + __set_MITCMCR(mitcmcr); +#endif + +#if CONFIG_ECC_DTCM_ENABLE + uint64_t mdtcmcr = __get_MDTCMCR(); + mdtcmcr |= MDTCMCR_ECC_EN_Msk; + __set_MDTCMCR(mdtcmcr); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + fpp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/vectors.S new file mode 100644 index 00000000000..e5417cc677a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv-cp/vectors.S @@ -0,0 +1,983 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_INTC_CLIC_PLIC + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) + +.section .bss +.align 3 +.global irq_nested_level +irq_nested_level: + .space 8 * CONFIG_NR_CPUS +irq_nested_level_end: + +irq_nested_mcause: + .space 8 * CONFIG_NR_CPUS * IRQ_NESTED_MAX +irq_nested_mcause_end: +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + sd ra, (0)(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrr a1, mcause + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, (0)(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#else /* CONFIG_SUPPORT_IRQ_NESTED */ + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -(8+8+8+8) + sd t0, 0(sp) + sd t1, (4+4)(sp) + sd t2, (8+8)(sp) + sd t3, (12+12)(sp) + + csrr t3, mhartid + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, 1 + sd t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + csrr t1, mcause + sd t1, (t0) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -16 + sd s0, (sp) + csrr t0, mepc + sd t0, 8(sp) +#endif + csrw mscratch, sp + la sp, g_base_irqstack + addi t1, t3, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + j .Lnested2 +.Lnested1: + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + csrs mstatus, 8 + + sd ra, 0(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from irq_nested_mcause */ + csrr t3, mhartid + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + ld a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + sd t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 16 +#endif + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + mv t1, t0 + + ld t0, (t1) + andi t0, t0, 0x3FF + srli a0, a1, 11 + slli a0, a0, 11 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + mret +#endif /* CONFIG_SUPPORT_IRQ_NESTED */ + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + j Default_IRQHandler + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 )(sp) + sd x3, ( 8+8)(sp) + sd x4, ( 12+12)(sp) + sd x5, ( 16+16)(sp) + sd x6, ( 20+20)(sp) + sd x7, ( 24+24)(sp) + sd x8, ( 28+28)(sp) + sd x9, ( 32+32)(sp) + sd x10,( 36+36)(sp) + sd x11,( 40+40)(sp) + sd x12,( 44+44)(sp) + sd x13,( 48+48)(sp) + sd x14,( 52+52)(sp) + sd x15,( 56+56)(sp) + sd x16,( 60+60)(sp) + sd x17,( 64+64)(sp) + sd x18,( 68+68)(sp) + sd x19,( 72+72)(sp) + sd x20,( 76+76)(sp) + sd x21,( 80+80)(sp) + sd x22,( 84+84)(sp) + sd x23,( 88+88)(sp) + sd x24,( 92+92)(sp) + sd x25,( 96+96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4+4)(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler + +#else /* !CONFIG_INTC_CLIC_PLIC */ + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler +#endif + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE +.text + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .size ECC_L1_Handler, . - ECC_L1_Handler +#endif /* CONFIG_INTC_CLIC_PLIC */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/startup.S new file mode 100644 index 00000000000..f6cd7865859 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/startup.S @@ -0,0 +1,292 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: +#if CONFIG_INTC_CLIC_PLIC + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword tspend_handler /* 3 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Mcoret_Handler /* 7 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_IRQHandler /* 11 */ + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + .dword Default_Handler + + /* External interrupts */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + .dword ECC_L1_Handler /* 16 */ +#else + .dword Default_IRQHandler /* 16 */ +#endif +#if CONFIG_IRQ_LATENCY + .dword IRQ_LATENCY_IRQHandler +#else + .dword Default_IRQHandler +#endif + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler + .dword Default_IRQHandler +#else + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif +#endif + + .size __Vectors, . - __Vectors + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop +#if CONFIG_INTC_CLIC_PLIC + la a0, Default_Handler + ori a0, a0, 3 + csrw mtvec, a0 + + la a0, __Vectors + csrw mtvt, a0 +#else + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 +#endif + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/system.c new file mode 100644 index 00000000000..6b9b5b4d028 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/system.c @@ -0,0 +1,406 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if !CONFIG_INTC_CLIC_PLIC && CONFIG_SUPPORT_IRQ_NESTED +#error "Please disable CONFIG_SUPPORT_IRQ_NESTED in package.yaml when use PLIC." +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void fpp_init(void) +{ +#if CONFIG_FPP_ENABLE + csi_fpp_set_base_addr(0x19000000); + csi_fpp_enable(); +#endif +} + +#if CONFIG_INTC_CLIC_PLIC +static void clic_init(void) +{ + int i; + + /* get interrupt level from info */ + CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos); + + for (i = 0; i < 64; i++) { + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + CLIC->CLICINT[i].CTL = (CLIC->CLICINT[i].CTL & (~CLIC_INTCFG_PRIO_Msk)) | (0x1 << (8 - nlbits)); + CLIC->CLICINT[i].IP = 0; + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ + } + + /* tspend use positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_irq_enable(Machine_Software_IRQn); + + /* enable external plic interrupt */ + csi_irq_enable(Machine_External_IRQn); + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + CLIC->CLICINT[L1_CACHE_ECC_IRQn].ATTR = 0x3; + csi_irq_enable(L1_CACHE_ECC_IRQn); +#endif +} +#endif + +static void interrupt_init(void) +{ + int i; + +#if CONFIG_INTC_CLIC_PLIC + clic_init(); + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM - PLIC_IRQ_OFFSET; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; +#else + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +#endif +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ +#if CONFIG_CPU_XUANTIE_R908_CP || CONFIG_CPU_XUANTIE_R908FD_CP || CONFIG_CPU_XUANTIE_R908FDV_CP + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status &= ~(1 << 22); + status |= (1 << 24 | 1 << 15); + __set_MXSTATUS(status); +#else + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); +#endif + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#if CONFIG_ECC_ITCM_ENABLE + uint64_t mitcmcr = __get_MITCMCR(); + mitcmcr |= MITCMCR_ECC_EN_Msk; + __set_MITCMCR(mitcmcr); +#endif + +#if CONFIG_ECC_DTCM_ENABLE + uint64_t mdtcmcr = __get_MDTCMCR(); + mdtcmcr |= MDTCMCR_ECC_EN_Msk; + __set_MDTCMCR(mdtcmcr); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + fpp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/vectors.S new file mode 100644 index 00000000000..e5417cc677a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r908fdv/vectors.S @@ -0,0 +1,983 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +#if CONFIG_INTC_CLIC_PLIC + +/* Enable interrupts when returning from the handler */ +#define MSTATUS_PRV1 0x1880 + +#if CONFIG_SUPPORT_IRQ_NESTED +#define IRQ_NESTED_MAX (6) + +.section .bss +.align 3 +.global irq_nested_level +irq_nested_level: + .space 8 * CONFIG_NR_CPUS +irq_nested_level_end: + +irq_nested_mcause: + .space 8 * CONFIG_NR_CPUS * IRQ_NESTED_MAX +irq_nested_mcause_end: +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + sd ra, (0)(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrr a1, mcause + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, (0)(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#else /* CONFIG_SUPPORT_IRQ_NESTED */ + .align 3 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: + addi sp, sp, -(8+8+8+8) + sd t0, 0(sp) + sd t1, (4+4)(sp) + sd t2, (8+8)(sp) + sd t3, (12+12)(sp) + + csrr t3, mhartid + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, 1 + sd t1, (t0) + + li t0, IRQ_NESTED_MAX + /* nested too deeply, may be error happens */ + bgt t1, t0, Default_Handler + + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + csrr t1, mcause + sd t1, (t0) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + li t0, 1 + bgt t1, t0, .Lnested1 + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -16 + sd s0, (sp) + csrr t0, mepc + sd t0, 8(sp) +#endif + csrw mscratch, sp + la sp, g_base_irqstack + addi t1, t3, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + j .Lnested2 +.Lnested1: + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) +.Lnested2: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, -(76+76) +#else + addi sp, sp, -(72+72) +#endif + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + csrr t0, mepc + sd t1, (64+64)(sp) + sd t0, (68+68)(sp) +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t0, mstatus + sd t0, (72+72)(sp) +#endif + csrs mstatus, 8 + + sd ra, 0(sp) + sd t2, (12+12)(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t0, do_irq + jalr t0 + + csrc mstatus, 8 + + /* get mcause from irq_nested_mcause */ + csrr t3, mhartid + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + + ld a1, (t0) + andi a0, a1, 0x3FF + slli a0, a0, 2 + + /* clic clear pending */ + li a2, 0x0c011000 /* clic base address */ + add a2, a2, a0 + lb a3, 0(a2) + li a4, 1 + not a4, a4 + and a5, a4, a3 + sb a5, 0(a2) + + la t0, irq_nested_level + slli t2, t3, 3 /* mhartid * 8 */ + add t0, t0, t2 + ld t1, (t0) + addi t1, t1, -1 + sd t1, (t0) + bgt t1, zero, .Lnested3 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + csrw mcause, a1 + + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 16 +#endif + ld t0, 0(sp) + ld t1, (4+4)(sp) + ld t2, (8+8)(sp) + ld t3, (12+12)(sp) + addi sp, sp, (8+8+8+8) + mret + +.Lnested3: + /* keep mpil in current mcause & load exception code before */ + addi t1, t1, -1 + la t0, irq_nested_mcause + li t2, 8 * IRQ_NESTED_MAX + mul t2, t2, t3 + slli t1, t1, 3 + add t2, t2, t1 + add t0, t0, t2 + mv t1, t0 + + ld t0, (t1) + andi t0, t0, 0x3FF + srli a0, a1, 11 + slli a0, a0, 11 + or t0, a0, t0 + csrw mcause, t0 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (68+68)(sp) + csrw mepc, t0 + + li t0, MSTATUS_PRV1 + csrs mstatus, t0 + + ld ra, 0(sp) + ld t0, (4+4)(sp) + ld t1, (8+8)(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + addi sp, sp, (76+76) +#else + addi sp, sp, (72+72) +#endif + mret +#endif /* CONFIG_SUPPORT_IRQ_NESTED */ + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + j Default_IRQHandler + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 )(sp) + sd x3, ( 8+8)(sp) + sd x4, ( 12+12)(sp) + sd x5, ( 16+16)(sp) + sd x6, ( 20+20)(sp) + sd x7, ( 24+24)(sp) + sd x8, ( 28+28)(sp) + sd x9, ( 32+32)(sp) + sd x10,( 36+36)(sp) + sd x11,( 40+40)(sp) + sd x12,( 44+44)(sp) + sd x13,( 48+48)(sp) + sd x14,( 52+52)(sp) + sd x15,( 56+56)(sp) + sd x16,( 60+60)(sp) + sd x17,( 64+64)(sp) + sd x18,( 68+68)(sp) + sd x19,( 72+72)(sp) + sd x20,( 76+76)(sp) + sd x21,( 80+80)(sp) + sd x22,( 84+84)(sp) + sd x23,( 88+88)(sp) + sd x24,( 92+92)(sp) + sd x25,( 96+96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4+4)(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler tspend_handler + +#else /* !CONFIG_INTC_CLIC_PLIC */ + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw sstatus, t0 + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler +#endif + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_ITCM_ENABLE || CONFIG_ECC_DTCM_ENABLE +.text + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + + ld t0, (72+72)(sp) + csrw mstatus, t0 + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + .size ECC_L1_Handler, . - ECC_L1_Handler +#endif /* CONFIG_INTC_CLIC_PLIC */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/system.c new file mode 100644 index 00000000000..dfa4b9bfb9a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/system.c @@ -0,0 +1,316 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/vectors.S new file mode 100644 index 00000000000..8256bdf9871 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r910/vectors.S @@ -0,0 +1,526 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/startup.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/startup.S new file mode 100644 index 00000000000..92ba69989b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/startup.S @@ -0,0 +1,188 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 + +#ifndef CONFIG_NR_CPUS +#define CONFIG_NR_CPUS 1 +#endif + +.globl Reset_Handler + +.section .vectors + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + j Default_Handler /* 0 */ + j Stspend_Handler /* 1 */ + j Default_Handler /* 2 */ + j Mtspend_Handler /* 3 */ + j Default_Handler /* 4 */ + j Scoret_Handler /* 5 */ + j Default_Handler /* 6 */ + j Mcoret_Handler /* 7 */ + j Default_Handler /* 8 */ + j Sirq_Handler /* 9 */ + j Default_Handler /* 10 */ + j Mirq_Handler /* 11 */ + j Default_Handler /* 12 */ + j Default_Handler /* 13 */ + j Default_Handler /* 14 */ + j Default_Handler /* 15 */ +#if CONFIG_ECC_L1_ENABLE + j ECC_L1_Handler /* 16 */ +#else + j Default_Handler /* 16 */ +#endif + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 + .rept 9 + .long 0 + .endr + .long Reset_Handler +_start: + .type Reset_Handler, %function +Reset_Handler: +.option push +.option norelax + /* disable ie and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* Disable MIE to avoid triggering interrupts before the first task starts. */ + /* This bit is set when a task recovers context. */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrc mstatus, (1 << 1) +#else + csrc mstatus, (1 << 3) +#endif + + la gp, __global_pointer$ +.option pop + la a0, __Vectors + li a1, 0x1 + or a0, a0,a1 + csrw mtvec, a0 + + /* get cpu id */ + csrr a0, mhartid + +#if defined(CONFIG_SMP) && CONFIG_SMP + /* check if hart is within range */ + /* tp: hart id */ + li t0, CONFIG_NR_CPUS + bge a0, t0, hart_out_of_bounds_loop +#endif + +#ifdef CONFIG_KERNEL_NONE + la sp, g_base_mainstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_MAINSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_MAINSTACK + g_base_mainstack */ +#else + la sp, g_base_irqstack + addi t1, a0, 1 + li t2, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t2 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ +#endif + + /* other cpu core, jump to cpu entry directly */ + bnez a0, secondary_cpu_entry + +#ifndef __NO_SYSTEM_INIT + la a0, SystemInit + jalr a0 +#endif + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + la a0, smode_init + jalr a0 +#endif + +#ifdef CONFIG_KERNEL_NONE + /* Enable interrupt */ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + csrs sstatus, (1 << 1) +#else + csrs mstatus, (1 << 3) +#endif +#endif + + la a0, pre_main + jalr a0 + +.size Reset_Handler, . - Reset_Handler + +__exit: + j __exit + + .type secondary_cpu_entry, %function +secondary_cpu_entry: +#if defined(CONFIG_SMP) && CONFIG_SMP + la a0, secondary_boot_flag + ld a0, 0(a0) + li a1, 0xa55a + beq a0, a1, 1f +#endif + j secondary_cpu_entry + +#if defined(CONFIG_SMP) && CONFIG_SMP +1: + jal secondary_cpu_c_start + +.size secondary_cpu_entry, . - secondary_cpu_entry + +hart_out_of_bounds_loop: + /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */ + wfi + j hart_out_of_bounds_loop +#endif + +.section .stack + .align 4 + .global g_base_irqstack + .global g_top_irqstack +g_base_irqstack: + .space CONFIG_ARCH_INTERRUPTSTACK * CONFIG_NR_CPUS +g_top_irqstack: + +#ifdef CONFIG_KERNEL_NONE + .align 4 + .global g_base_mainstack + .global g_top_mainstack +g_base_mainstack: + .space CONFIG_ARCH_MAINSTACK * CONFIG_NR_CPUS +g_top_mainstack: +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP +.data +.global secondary_boot_flag +.align 3 +secondary_boot_flag: + .dword 0 +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/system.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/system.c new file mode 100644 index 00000000000..dfa4b9bfb9a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/system.c @@ -0,0 +1,316 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include "riscv_csr.h" + +#if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE) +#error "Please check the current system is baremetal or not!!!" +#endif + +#if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP) +#if CONFIG_NR_CPUS > 1 +#error "Please define CONFIG_NR_CPUS as 1 or do not need define." +#endif +#endif + +#if CONFIG_ECC_L2_ENABLE +static csi_dev_t ecc_l2_dev; +#endif + +extern void section_data_copy(void); +extern void section_ram_code_copy(void); +extern void section_bss_clear(void); + +#ifdef CONFIG_RISCV_SMODE +extern unsigned long __Vectors; +unsigned long page_table_l2[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l1[512] __attribute__ ((aligned(4096))); +unsigned long page_table_l0[512] __attribute__ ((aligned(4096))); + +void _mmu_init(void) __attribute__((noinline)); +void _mmu_init(void) +{ +#if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 + unsigned long status = __get_MXSTATUS(); + /* open MAEE for thead-mmu extension */ + status |= (1 << 21); + __set_MXSTATUS(status); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 + unsigned long envcfgh = __get_MENVCFGH(); + /* enable svpbmt */ + envcfgh |= (1 << 30); + __set_MENVCFGH(envcfgh); + + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */ + for (unsigned long i = 1; i < 256; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + for (unsigned long i = 256; i < 512; i++) { + page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } +#else + unsigned long envcfg = __get_MENVCFG(); + /* enable svpbmt */ + envcfg |= (1ull << 62); + __set_MENVCFG(envcfg); + + page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10; + page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10; + /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */ + for (unsigned long i = 0; i < 256; i++) { + page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */ + for (unsigned long i = 1; i < 512; i++) { + page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; + } + + /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */ + page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1; +#endif + +#if __riscv_xlen == 64 + csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2)); +#endif + csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1)); + csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0)); + csi_mmu_invalid_tlb_all(); +#if __riscv_xlen == 64 + __set_SATP(((unsigned long)&page_table_l2 >> 12)); + csi_mmu_set_mode(MMU_MODE_39); + csi_mmu_enable(); +#else + __set_SATP(((unsigned long)&page_table_l1 >> 12)); + csi_mmu_set_mode(MMU_MODE_32); + csi_mmu_enable(); +#endif +} + +void _system_switchto_smode(void) +{ + unsigned long m_status = __get_MSTATUS(); + m_status &= ~MSTATUS_TVM_MASK; + m_status &= ~MSTATUS_MPP_MASK; + m_status |= MSTATUS_MPP_S; + __set_MSTATUS(m_status); + + /* setup S-Mode csr regs */ + __set_STVEC((unsigned long)(&__Vectors) | 0x1); + //FIXME: + __ASM("auipc a0, 0"); + __ASM("addi a0, a0, 14"); + __ASM("csrw mepc, a0"); + __ASM("mret"); +} + +void _system_init_for_smode(void) +{ + _system_switchto_smode(); +} + +void smode_init(void) +{ + /* may be not clear after reset on FPGA */ + csi_mmu_disable(); + _mmu_init(); + _system_init_for_smode(); +} +#endif + +/** + * @brief initialize pmp + * @param None + * @return None + */ +static void pmp_init(void) +{ + long addr; + + addr = 0x90000000UL >> 2; + __set_PMPADDR0(addr); + __set_PMPxCFG(0, 0x8f); +} + +static void interrupt_init(void) +{ + int i; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_PRIO[i] = 31; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_IP[i] = 0; + } + + for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) { + PLIC->PLIC_H0_MIE[i] = 0; + PLIC->PLIC_H0_SIE[i] = 0; + } + + /* set hart threshold 0, enable all interrupt */ + PLIC->PLIC_H0_MTH = 0; + PLIC->PLIC_H0_STH = 0; + + for (i = 0; i < CONFIG_IRQ_NUM; i++) { + PLIC->PLIC_H0_MCLAIM = i; + PLIC->PLIC_H0_SCLAIM = i; + } + + /* set PLIC_PER */ + PLIC->PLIC_PER = 0x1; + + /* enable MEIE & MTIE & MSIE */ + uint32_t mie = __get_MIE(); + mie |= (1 << 11 | 1 << 7 | 1 << 3); +#if CONFIG_ECC_L1_ENABLE + mie |= (1 << 16); +#endif + __set_MIE(mie); +} + +static void section_init(void) +{ +#if CONFIG_XIP + section_data_copy(); + section_ram_code_copy(); + csi_dcache_clean(); + csi_icache_invalid(); +#endif + + section_bss_clear(); +} + +static void cache_init(void) +{ + /* enable cache */ + csi_dcache_enable(); + csi_icache_enable(); +} + +/** + * @brief initialize the system + * Initialize the psr and vbr. + * @param None + * @return None + */ +void SystemInit(void) +{ + /* enable theadisaee & MM */ + unsigned long status = __get_MXSTATUS(); + status |= (1 << 22 | 1 << 15); + __set_MXSTATUS(status); + +#if __riscv_flen == 64 + /* enable float ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_FS_SHIFT); + __set_MSTATUS(status); +#endif +#ifdef __riscv_vector + /* enable vector ISA */ + status = __get_MSTATUS(); + status |= (1 << MSTATUS_VS_SHIFT); + __set_MSTATUS(status); +#endif + +#if CONFIG_ECC_L1_ENABLE + /* enable L1 cache ecc */ + uint64_t mhint = __get_MHINT(); + mhint |= (0x1 << 19); + __set_MHINT(mhint); +#endif + +#if CONFIG_ECC_L2_ENABLE + /* enable L2 cache ecc */ + uint64_t mccr2 = __get_MCCR2(); + mccr2 |= (0x1 << 1); + __set_MCCR2(mccr2); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable ecall delegate */ + unsigned long medeleg = __get_MEDELEG(); + medeleg |= (1 << 9); + __set_MEDELEG(medeleg); + + /* enable interrupt delegate */ + unsigned long mideleg = __get_MIDELEG(); + mideleg |= 0x222; + __set_MIDELEG(mideleg); +#endif + +#ifdef CONFIG_RISCV_SMODE + /* enable mcounteren for s-mode */ + __set_MCOUNTEREN(0xffffffff); + +#if CBO_INSN_SUPPORT + unsigned long envcfg = __get_MENVCFG(); + /* enable CBIE & CBCFE & CBZE on lower priviledge */ + envcfg |= (3 << 4 | 1 << 6 | 1 << 7); + __set_MENVCFG(envcfg); +#endif +#endif + + cache_init(); + section_init(); + pmp_init(); + + interrupt_init(); + soc_set_sys_freq(20000000); + csi_tick_init(); + +#if CONFIG_ECC_L2_ENABLE + extern void ecc_l2_irqhandler(void *arg); + /* l2 cache ecc interrupt register */ + ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn; + csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev); + csi_irq_enable(ecc_l2_dev.irq_num); +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/trap_c.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/trap_c.c new file mode 100644 index 00000000000..f36e86b2595 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/trap_c.c @@ -0,0 +1,64 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#if defined(AOS_COMP_DEBUG) && (AOS_COMP_DEBUG > 0) +#include +#else +#define printk printf +#endif + +void (*trap_c_callback)(void); + +void trap_c(uintptr_t *regs) +{ + int i; + unsigned long vec = 0; + + vec = __get_MCAUSE(); + + printk("CPU Exception(mcause);: NO.0x%lx", vec); + printk("\n"); + + for (i = 0; i < 31; i++) { + printk("x%d: %p\t", i + 1, (void *)regs[i]); + + if ((i % 4) == 3) { + printk("\n"); + } + } + + printk("\n"); + printk("mepc : %p\n", (void *)regs[31]); + printk("mstatus: %p\n", (void *)regs[32]); + + if (trap_c_callback) { + trap_c_callback(); + } + + while (1); +} + +__attribute__((weak)) void exceptionHandler(void *context) +{ + trap_c((uintptr_t *)context); +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/vectors.S b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/vectors.S new file mode 100644 index 00000000000..8256bdf9871 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/arch/r920/vectors.S @@ -0,0 +1,526 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 "riscv_asm_macro.h" + +.section .stack + .align 4 + .global g_trapstackbase + .global g_top_trapstack +g_trapstackbase: + .space CONFIG_ARCH_INTERRUPTSTACK +g_top_trapstack: + +.text +.global _interrupt_return_address + + .align 3 + .weak Scoret_Handler + .type Scoret_Handler, %function +Scoret_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mcoret_Handler + .type Mcoret_Handler, %function +Mcoret_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, CORET_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + +#if CONFIG_ECC_L1_ENABLE + .align 3 + .weak ECC_L1_Handler + .type ECC_L1_Handler, %function +ECC_L1_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, ECC_L1_IRQHandler + jalr t2 + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret +#endif + + .align 3 + .weak Sirq_Handler + .type Sirq_Handler, %function +Sirq_Handler: + csrw sscratch, sp + la sp, g_top_irqstack + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, sepc + sd t0, (68+68)(sp) + csrr t0, sstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, sstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_SSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw sstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw sepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, sscratch + sret + + + .align 3 + .weak Mirq_Handler + .type Mirq_Handler, %function +Mirq_Handler: + addi sp, sp, -16 + sd t0, (0)(sp) + sd t1, (8)(sp) +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sd s0, (sp) +#endif + csrw mscratch, sp + + csrr t0, mhartid + la sp, g_base_irqstack + addi t1, t0, 1 + li t0, CONFIG_ARCH_INTERRUPTSTACK + mul t1, t1, t0 + add sp, sp, t1 /* sp = (cpuid + 1) * CONFIG_ARCH_INTERRUPTSTACK + g_base_irqstack */ + + addi sp, sp, -(76+76) + sd t0, (4+4)(sp) + sd t1, (8+8)(sp) + sd t2, (12+12)(sp) + + csrr t0, mepc + sd t0, (68+68)(sp) + csrr t0, mstatus + sd t0, (72+72)(sp) + + sd ra, (0 +0 )(sp) + sd a0, (16+16)(sp) + sd a1, (20+20)(sp) + sd a2, (24+24)(sp) + sd a3, (28+28)(sp) + sd a4, (32+32)(sp) + sd a5, (36+36)(sp) + sd a6, (40+40)(sp) + sd a7, (44+44)(sp) + sd t3, (48+48)(sp) + sd t4, (52+52)(sp) + sd t5, (56+56)(sp) + sd t6, (60+60)(sp) + +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + csrr t3, mstatus +#endif + SAVE_FLOAT_REGISTERS + SAVE_VECTOR_REGISTERS + + la t2, do_irq + jalr t2 +_interrupt_return_address: +#if CONFIG_CHECK_FPU_DIRTY || CONFIG_CHECK_VECTOR_DIRTY + RESTORE_MSTATUS +#endif + RESTORE_VECTOR_REGISTERS + RESTORE_FLOAT_REGISTERS + +#if (!CONFIG_CHECK_FPU_DIRTY) && (!CONFIG_CHECK_VECTOR_DIRTY) + ld t0, (72+72)(sp) + csrw mstatus, t0 +#endif + ld t0, (68+68)(sp) + csrw mepc, t0 + + ld ra, (0 +0 )(sp) + ld t0, (4 +4 )(sp) + ld t1, (8 +8 )(sp) + ld t2, (12+12)(sp) + ld a0, (16+16)(sp) + ld a1, (20+20)(sp) + ld a2, (24+24)(sp) + ld a3, (28+28)(sp) + ld a4, (32+32)(sp) + ld a5, (36+36)(sp) + ld a6, (40+40)(sp) + ld a7, (44+44)(sp) + ld t3, (48+48)(sp) + ld t4, (52+52)(sp) + ld t5, (56+56)(sp) + ld t6, (60+60)(sp) + + addi sp, sp, (76+76) + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + ld t0, (0)(sp) + ld t1, (8)(sp) + addi sp, sp, 16 + mret + + +/****************************************************************************** + * Functions: + * void trap(void); + * default exception handler + ******************************************************************************/ + .align 3 + .global trap + .type trap, %function +trap: + csrw mscratch, sp + la sp, g_top_trapstack + addi sp, sp, -(140+140) + sd x1, ( 0 + 0 )(sp) + sd x3, ( 8 + 8 )(sp) + sd x4, ( 12+ 12)(sp) + sd x5, ( 16+ 16)(sp) + sd x6, ( 20+ 20)(sp) + sd x7, ( 24+ 24)(sp) + sd x8, ( 28+ 28)(sp) + sd x9, ( 32+ 32)(sp) + sd x10,( 36+ 36)(sp) + sd x11,( 40+ 40)(sp) + sd x12,( 44+ 44)(sp) + sd x13,( 48+ 48)(sp) + sd x14,( 52+ 52)(sp) + sd x15,( 56+ 56)(sp) + sd x16,( 60+ 60)(sp) + sd x17,( 64+ 64)(sp) + sd x18,( 68+ 68)(sp) + sd x19,( 72+ 72)(sp) + sd x20,( 76+ 76)(sp) + sd x21,( 80+ 80)(sp) + sd x22,( 84+ 84)(sp) + sd x23,( 88+ 88)(sp) + sd x24,( 92+ 92)(sp) + sd x25,( 96+ 96)(sp) + sd x26,(100+100)(sp) + sd x27,(104+104)(sp) + sd x28,(108+108)(sp) + sd x29,(112+112)(sp) + sd x30,(116+116)(sp) + sd x31,(120+120)(sp) + csrr a0, mepc + sd a0, (124+124)(sp) + csrr a0, mstatus + sd a0, (128+128)(sp) + csrr a0, mcause + sd a0, (132+132)(sp) + csrr a0, mtval + sd a0, (136+136)(sp) + csrr a0, mscratch + sd a0, ( 4 + 4 )(sp) + + mv a0, sp + la a1, exceptionHandler + jalr a1 + + .align 3 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + j trap + + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler Stspend_Handler + def_irq_handler Mtspend_Handler + def_irq_handler CORET_IRQHandler diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/SConscript b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/SConscript new file mode 100644 index 00000000000..a8cba7cd859 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/SConscript @@ -0,0 +1,11 @@ +from building import * +import os + +cwd = GetCurrentDir() +CPPPATH = [cwd] +src = ['uart.c'] +src += ['dw_uart_ll.c'] + +group = DefineGroup('startup', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/adc.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/adc.c new file mode 100644 index 00000000000..fe4724a6ca8 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/adc.c @@ -0,0 +1,450 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file wj_adc.c + * @brief CSI Source File for ADC Driver + * @version V1.0 + * @date 2020-03-05 + ******************************************************************************/ + +#include + +#include +#include +#include + +static void wj_adc_irqhandler(void *args) +{ + + ///< TODO:获取ADC中断的状态 + ///< TODO:清除ADC中断 + ///< TODO:根据ADC的中断状态处理中断 + +} + +void wj_adc_dma_event_cb(csi_dma_ch_t *dma, csi_dma_event_t event, void *arg) +{ + csi_adc_t *adc; + + adc = (csi_adc_t *)dma->parent; + + if (event == DMA_EVENT_TRANSFER_DONE) { + ///< 关闭DMA通道 + csi_dma_ch_stop(dma); + adc->num = 0U; + adc->state.readable = 1U; + + if (adc->callback) { + soc_dcache_clean_invalid_range((unsigned long)adc->data, adc->num * 4U); + ///< 执行ADC DMA传输完成的用户回调函数 + adc->callback(adc, ADC_EVENT_CONVERT_COMPLETE, adc->arg); + } + } +} + +static csi_error_t wj_adc_start_intr(csi_adc_t *adc) +{ + + ///< 使能ADC的中断控制器中对应的中断 + csi_irq_enable((uint32_t)adc->dev.irq_num); + ///< TODO:使能ADC的中断 + + ///< TODO:打开ADC控制器 + return CSI_OK; +} + +static csi_error_t wj_adc_start_dma(csi_adc_t *adc) +{ + csi_dma_ch_config_t config; + + config.src_inc = DMA_ADDR_CONSTANT; + config.dst_inc = DMA_ADDR_INC; + config.src_tw = DMA_DATA_WIDTH_32_BITS; + config.dst_tw = DMA_DATA_WIDTH_32_BITS; + + config.group_len = 4U; + config.trans_dir = DMA_PERH2MEM; + config.handshake = 81U; + ///< 配置ADC的DMA通道 + csi_dma_ch_config(adc->dma, &config); + ///< 禁止中断控制器对应的中断 + csi_irq_disable((uint32_t)adc->dev.irq_num); + soc_dcache_clean_invalid_range((unsigned long)adc->data, adc->num * 4U); + + ///< TODO:调用csi_dma_ch_start接口打开ADC的DMA通道 + ///< TODO:打开ADC + return CSI_OK; +} + +static csi_error_t wj_adc_stop_intr(csi_adc_t *adc) +{ + csi_error_t ret = CSI_OK; + + ///< TODO:关闭ADC的中断 + + ///< TODO:关闭ADC + + return ret; +} + +static csi_error_t wj_adc_stop_dma(csi_adc_t *adc) +{ + csi_error_t ret = CSI_OK; + + ///< TODO:关闭ADC + + return ret; +} + +csi_error_t csi_adc_init(csi_adc_t *adc, uint32_t idx) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + csi_error_t ret = CSI_OK; + + adc->priv = 0U; + + ///< 获取中断号、基地址等相关信息 + if (target_get(DEV_WJ_ADC_TAG, idx, &adc->dev) != CSI_OK) { + ret = CSI_ERROR; + } else { + + adc->state.writeable = 1U; + adc->state.readable = 1U; + adc->state.error = 0U; + adc->callback = NULL; + adc->arg = NULL; + adc->data = NULL; + adc->dma = NULL; + adc->start = NULL; + adc->stop = NULL; + + ///< TODO:关闭ADC控制器 + ///< TODO:打开ADC控制器 + + } + + return ret; +} + +void csi_adc_uninit(csi_adc_t *adc) +{ + CSI_PARAM_CHK_NORETVAL(adc); + + ///< TODO:关闭ADC所有的通道 + ///< TODO:关闭ADC控制器 +} + +csi_error_t csi_adc_set_buffer(csi_adc_t *adc, uint32_t *data, uint32_t num) +{ + csi_error_t ret = CSI_OK; + CSI_PARAM_CHK(adc, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(num, CSI_ERROR); + + if (num == 0U) { + ret = CSI_ERROR; + } else { + adc->data = data; + adc->num = num; + ret = CSI_OK; + } + + return ret; +} + +csi_error_t csi_adc_start(csi_adc_t *adc) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + if (adc->state.readable == 0U) { + ret = CSI_BUSY; + return ret; + } + + if (adc->state.writeable == 0U) { + ret = CSI_BUSY; + return ret; + } + + ///< TODO:打开ADC控制器 + + return ret; +} + +csi_error_t csi_adc_stop(csi_adc_t *adc) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + ///< TODO:关闭ADC + + adc->state.readable = 1U; + adc->state.writeable = 1U; + adc->data = NULL; + adc->num = 0U; + + return ret; +} + +csi_error_t csi_adc_channel_enable(csi_adc_t *adc, uint8_t ch_id, bool is_enable) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + csi_error_t ret = CSI_OK; + + if (is_enable) { + ///< TODO:选择ADC的通道 + } else { + ///< TODO:关闭指定的ADC通道 + } + + return ret; +} + +csi_error_t csi_adc_channel_sampling_time(csi_adc_t *adc, uint8_t ch_id, uint16_t clock_num) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + return CSI_UNSUPPORTED; +} + +csi_error_t csi_adc_sampling_time(csi_adc_t *adc, uint16_t clock_num) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + ///< TODO:设置ADC的采样时间 + + return ret; +} + + +uint32_t csi_adc_freq_div(csi_adc_t *adc, uint32_t div) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + uint32_t ret = 0; + + ///< TODO:设置ADC的分频 + ///< TODO:获取ADC分频后使用的频率ret,需要用户自己获取ret + + return ret; +} + +int32_t csi_adc_read(csi_adc_t *adc) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + + int32_t ret = CSI_OK; + + ///< TODO:在一定时间内ADC读数据的标志位不为0,否则超时退出 + ///< TODO:读数据寄存器获取ADC转换的数据到ret + + return ret; +} + +csi_error_t csi_adc_get_state(csi_adc_t *adc, csi_state_t *state) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + *state = adc->state; + return CSI_OK; +} + +uint32_t csi_adc_get_freq(csi_adc_t *adc) +{ + CSI_PARAM_CHK(adc, 0U); + uint32_t freq = 0U; + + ///< TODO:获取ADC的分频div + ///< TODO:获取ADC分频后使用的频率freq + + return freq; + +} + +csi_error_t csi_adc_attach_callback(csi_adc_t *adc, void *callback, void *arg) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + CSI_PARAM_CHK(callback, CSI_ERROR); + + adc->callback = callback; + adc->arg = arg; + adc->start = wj_adc_start_intr; + adc->stop = wj_adc_stop_intr; + + ///< 注册ADC的中断服务函数,使能中断控制器对应的中断 + csi_irq_attach((uint32_t)adc->dev.irq_num, &wj_adc_irqhandler, &adc->dev); + csi_irq_enable((uint32_t)adc->dev.irq_num); + return CSI_OK; + +} + +void csi_adc_detach_callback(csi_adc_t *adc) +{ + CSI_PARAM_CHK_NORETVAL(adc); + + adc->callback = NULL; + adc->arg = NULL; + adc->start = NULL; + adc->stop = NULL; + + ///< 禁止中断控制器对应的中断 + csi_irq_disable((uint32_t)adc->dev.irq_num); +} + +csi_error_t csi_adc_start_async(csi_adc_t *adc) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + if ((adc->data == NULL) || (adc->num == 0U)) { + ret = CSI_ERROR; + return ret; + } + + /* rx buffer not full */ + if (adc->state.readable == 0U) { + ret = CSI_BUSY; + return ret; + } + + /* last conversion existed */ + if (adc->state.writeable == 0U) { + ret = CSI_ERROR; + return ret; + } + + if (adc->start) { + ///< 执行ADC中断或者DMA传输完成中断回调函数 + adc->start(adc); + } + return ret; +} + +csi_error_t csi_adc_stop_async(csi_adc_t *adc) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + if (adc->stop) { + adc->stop(adc); + adc->state.readable = 1U; + adc->state.writeable = 1U; + adc->data = NULL; + adc->num = 0U; + } else { + ret = CSI_ERROR; + } + + return ret; +} + +csi_error_t csi_adc_continue_mode(csi_adc_t *adc, bool is_enable) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + + if (is_enable) { + ///< TODO:设置ADC为continue模式 + } else { + ///< TODO:设置ADC为single模式 + } + + ///< TODO:打开ADC的等待模式 + return CSI_OK; +} + +csi_error_t csi_adc_link_dma(csi_adc_t *adc, csi_dma_ch_t *dma) +{ + CSI_PARAM_CHK(adc, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + if (dma != NULL) { + dma->parent = adc; + ///< 申请DMA通道 + ret = csi_dma_ch_alloc(dma, -1, -1); + + if (ret == CSI_OK) { + ///< ADC DMA模式传输完成中断服务函数的注册 + csi_dma_ch_attach_callback(dma, wj_adc_dma_event_cb, NULL); + adc->dma = dma; + adc->start = wj_adc_start_dma; + adc->stop = wj_adc_stop_dma; + } else { + dma->parent = NULL; + } + } else { + if (adc->dma) { + ///< 释放DMA通道,注销ADC DMA模式传输完成中断服务函数 + csi_dma_ch_free(adc->dma); + csi_dma_ch_detach_callback(adc->dma); + adc->dma = NULL; + } + + if (adc->callback != NULL) { + adc->start = wj_adc_start_intr; + adc->stop = wj_adc_stop_intr; + } else { + adc->start = NULL; + adc->stop = NULL; + } + } + return ret; +} + +#ifdef CONFIG_PM +csi_error_t dw_adc_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action) +{ + CSI_PARAM_CHK(dev, CSI_ERROR); + + csi_error_t ret = CSI_OK; + csi_pm_dev_t *pm_dev = &dev->pm_dev; + wj_adc_regs_t *adc_base = (wj_adc_regs_t *)dev->reg_base; + + switch (action) { + case PM_DEV_SUSPEND: + ///< TODO:恢复ADC寄存器 + break; + + case PM_DEV_RESUME: + ///< TODO:保存ADC寄存器 + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +csi_error_t csi_adc_enable_pm(csi_adc_t *adc) +{ + ///< TODO:注册ADC低功耗处理函数dw_adc_pm_action +} + +void csi_adc_disable_pm(csi_adc_t *adc) +{ + csi_pm_dev_unregister(&adc->dev); +} +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/aes.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/aes.c new file mode 100644 index 00000000000..2749501431e --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/aes.c @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + */ + +/******************************************************* + * @file wj_aes.c + * @brief source file for aes csi driver + * @version V1.0 + * @date 2. July 2020 + * ******************************************************/ + +#include +#include + +#define AES_READ_CACHE_LITTLE(_addr_) \ + (((uint32_t) * (_addr_ + 0U) << 0) | ((uint32_t) * (_addr_ + 1U) << 8) | \ + ((uint32_t) * (_addr_ + 2U) << 16) | ((uint32_t) * (_addr_ + 3U) << 24)) + +#define AES_WRITE_CACHE_LITTLE(_addr_, _data_) \ + do { \ + *(_addr_+0U) = (uint8_t)*(_data_+0U); \ + *(_addr_+1U) = (uint8_t)*(_data_+1U); \ + *(_addr_+2U) = (uint8_t)*(_data_+2U); \ + *(_addr_+3U) = (uint8_t)*(_data_+3U); \ + } while(0) + +#define AES_IS_16BYTES_ALIGNMENT(_size_) ((_size_ % 16U) ? -1 : 0) + +/** + \brief Initialize AES Interface. Initializes the resources needed for the AES interface + \param[in] aes operate handle + \param[in] idx device id + \return error code \ref csi_error_t +*/ +csi_error_t csi_aes_init(csi_aes_t *aes, uint32_t idx) +{ + CSI_PARAM_CHK(aes, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + ///< 获取中断号、基地址等相关信息 + if (0 == target_get(DEV_WJ_AES_TAG, idx, &aes->dev)) { + + ///< TODO:对AES的所有寄存器进行清零操作 + + } else { + ret = CSI_ERROR; + } + + return ret; +} +/** + \brief De-initialize AES Interface. stops operation and releases the software resources used by the interface + \param[in] aes aes handle to operate + \return None +*/ +void csi_aes_uninit(csi_aes_t *aes) +{ + CSI_PARAM_CHK_NORETVAL(aes); + + ///< TODO:对AES的所有寄存器进行清零操作 + +} +/** + \brief Set encrypt key + \param[in] aes aes handle to operate + \param[in] key Pointer to the key buf + \param[in] key_len Pointer to \ref csi_aes_key_bits_t + \return error code \ref csi_error_t +*/ +csi_error_t csi_aes_set_encrypt_key(csi_aes_t *aes, void *key, csi_aes_key_bits_t key_len) +{ + CSI_PARAM_CHK(aes, CSI_ERROR); + csi_error_t ret = CSI_OK; + + switch (key_len) { + case AES_KEY_LEN_BITS_128: + ///< TODO:设置密钥长度为128 bits + break; + + case AES_KEY_LEN_BITS_192: + ///< TODO:设置密钥长度为128 bits + break; + + case AES_KEY_LEN_BITS_256: + ///< TODO:设置密钥长度为128 bits + break; + + default: + ret = CSI_ERROR; + break; + } + + ///< TODO:设置密钥 + ///< TODO:使能AES + ///< TODO:停止AES + + return ret; +} +/** + \brief Set decrypt key + \param[in] aes aes handle to operate + \param[in] key Pointer to the key buf + \param[in] key_len Pointer to \ref csi_aes_key_bits_t + \return error code \ref csi_error_t +*/ +csi_error_t csi_aes_set_decrypt_key(csi_aes_t *aes, void *key, csi_aes_key_bits_t key_len) +{ + CSI_PARAM_CHK(aes, CSI_ERROR); + csi_error_t ret = CSI_OK; + + switch (key_len) { + case AES_KEY_LEN_BITS_128: + ///< TODO:设置密钥长度为128 bits + break; + + case AES_KEY_LEN_BITS_192: + ///< TODO:设置密钥长度为128 bits + break; + + case AES_KEY_LEN_BITS_256: + ///< TODO:设置密钥长度为128 bits + break; + + default: + ret = CSI_ERROR; + break; + } + + ///< TODO:设置密钥 + ///< TODO:使能AES + ///< TODO:停止AES + + return ret; +} + +/** + \brief Aes ecb encrypt or decrypt + \param[in] aes aes handle to operate + \param[in] in Pointer to the Source data + \param[out] out Pointer to the Result data + \param[in] size the Source data size + \return error code \ref csi_error_t +*/ +csi_error_t csi_aes_ecb_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size) +{ + CSI_PARAM_CHK(aes, CSI_ERROR); + csi_error_t ret = CSI_OK; + + uint32_t i = 0U; + uint32_t j = 0U; + uint32_t n = 0U; + uint32_t temp; + ///< 加密数据长度判断 + if (0 == AES_IS_16BYTES_ALIGNMENT(size)) { + + ///< TODO:设置ECB模式 + ///< TODO:设置加密 + + /* set the text before aes calculating */ + for (i = 0U; i < size; i = i + 16U) { + for (j = 0U; j < 4U; j++) { + n = (j << 2) + i; ///< j:each time offset 4bytes, i:each time offset 16bytes + temp = AES_READ_CACHE_LITTLE((uint8_t *)in + n); + ///< TODO:写入待加密数据 + } + + ///< TODO:开始加密 + + ///< TODO:等待加密完成 + + for (j = 0U; j < 4U; j++) { + n = (j << 2) + i; ///< j:each time offset 4bytes, i:each time offset 16bytes + ///< TODO:获取加密数据到 temp + AES_WRITE_CACHE_LITTLE((uint8_t *)out + n, (uint8_t *)&temp); + } + } + } else { + ret = CSI_ERROR; + } + + return ret; +} +/** + \brief Aes ecb decrypt + \param[in] aes aes handle to operate + \param[in] in Pointer to the Source data + \param[out] out Pointer to the Result data + \param[in] size the Source data size + \return error code \ref csi_error_t +*/ +csi_error_t csi_aes_ecb_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size) +{ + CSI_PARAM_CHK(aes, CSI_ERROR); + csi_error_t ret = CSI_OK; + + uint32_t i = 0U; + uint32_t j = 0U; + uint32_t n = 0U; + uint32_t temp; + + if (0 == AES_IS_16BYTES_ALIGNMENT(size)) { + + ///< TODO:设置ECB模式 + ///< TODO:设置解密 + + + /* set the text before aes calculating */ + for (i = 0U; i < size; i = i + 16U) { + for (j = 0U; j < 4U; j++) { + n = (j << 2) + i; ///< j:each time offset 4bytes, i:each time offset 16bytes + temp = AES_READ_CACHE_LITTLE((uint8_t *)in + n); + ///< TODO:写入待解密数据 + } + + ///< TODO:开始解密 + + + ///< TODO:等待加密完成 + + for (j = 0U; j < 4U; j++) { + n = (j << 2) + i; ///< j:each time offset 4bytes, i:each time offset 16bytes + ///< TODO:获取解密数据到 temp + AES_WRITE_CACHE_LITTLE((uint8_t *)out + n, (uint8_t *)&temp); + } + } + } else { + ret = CSI_ERROR; + } + + return ret; +} +/** + \brief Aes cbc encrypt or decrypt + \param[in] aes aes handle to operate + \param[in] in Pointer to the Source data + \param[out] out Pointer to the Result data + \param[in] size the Source data size + \return error code \ref csi_error_t +*/ +csi_error_t csi_aes_cbc_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv) +{ + CSI_PARAM_CHK(aes, CSI_ERROR); + csi_error_t ret = CSI_OK; + + uint32_t i = 0U; + uint32_t j = 0U; + uint32_t n = 0U; + uint32_t temp; + + if (0 == AES_IS_16BYTES_ALIGNMENT(size)) { + ///< TODO:清除IV 值 + + ///< TODO:设置CBC模式 + ///< TODO:设置加密密 + + /* set iv if the mode is CBC */ + for (i = 0U; i < 4U; i++) { + temp = AES_READ_CACHE_LITTLE((uint8_t *)iv + (i << 2)); + ///< TODO:设置CBC值 + } + + /* set the text before aes calculating */ + for (i = 0U; i < size; i = i + 16U) { + for (j = 0U; j < 4U; j++) { + n = (j << 2) + i; ///< j:each time offset 4bytes, i:each time offset 16bytes + temp = AES_READ_CACHE_LITTLE((uint8_t *)in + n); + ///< TODO:写入待加密数据 + } + + ///< TODO:开始加密 + + ///< TODO:等待加密 + + for (j = 0U; j < 4U; j++) { + n = (j << 2) + i; ///< j:each time offset 4bytes, i:each time offset 16bytes + ///< TODO:获取加密数据到 temp + AES_WRITE_CACHE_LITTLE((uint8_t *)out + n, (uint8_t *)&temp); + } + } + + for (i = 0U; i < 4U; i++) { + ///< TODO:获取IV 数据到 temp + AES_WRITE_CACHE_LITTLE((uint8_t *)iv + (i << 2), (uint8_t *)&temp); + } + } else { + ret = CSI_ERROR; + } + + return ret; +} +/** + \brief Aes cbc decrypt + \param[in] aes aes handle to operate + \param[in] in Pointer to the Source data + \param[out] out Pointer to the Result data + \param[in] size the Source data size + \param[in] iv init vector + \return error code \ref csi_error_t +*/ +csi_error_t csi_aes_cbc_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv) +{ + CSI_PARAM_CHK(aes, CSI_ERROR); + csi_error_t ret = CSI_OK; + + uint32_t i = 0U; + uint32_t j = 0U; + uint32_t n = 0U; + uint32_t temp = 0U; + + if (0 == AES_IS_16BYTES_ALIGNMENT(size)) { + ///< TODO:清除IV 值 + + + ///< TODO:设置CBC模式 + ///< TODO:设置解密 + + ///< TODO:设置IV 值 + + /* set the text before aes calculating */ + for (i = 0U; i < size; i = i + 16U) { + for (j = 0U; j < 4U; j++) { + n = (j << 2) + i; ///< j:each time offset 4bytes, i:each time offset 16bytes + temp = AES_READ_CACHE_LITTLE((uint8_t *)in + n); + ///< TODO:写入待解密数据 + } + + ///< TODO:开始解密 + + ///< TODO:等待解密 + + + for (j = 0U; j < 4U; j++) { + n = (j << 2) + i; ///< j:each time offset 4bytes, i:each time offset 16bytes + ///< TODO:获取解密数据到 temp + AES_WRITE_CACHE_LITTLE((uint8_t *)out + n, (uint8_t *)&temp); + } + } + + for (i = 0U; i < 4U; i++) { + ///< TODO:获取IV数据到 temp + AES_WRITE_CACHE_LITTLE((uint8_t *)iv + (i << 2), (uint8_t *)&temp); + } + } else { + ret = CSI_ERROR; + } + + return ret; +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/clk.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/clk.c new file mode 100644 index 00000000000..9dbffac980d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/clk.c @@ -0,0 +1,62 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file clk.c + * @brief CSI Source File for clk Driver + * @version V1.0 + * @date 9. April 2020 + ******************************************************************************/ + +#include +#include +#include +#include +#include + +extern csi_clkmap_t clk_map[]; + +void csi_clk_enable(csi_dev_t *dev) +{ + csi_clkmap_t *map = clk_map; + + while (map->module != 0xFFFFFFFFU) { + if ((map->dev_tag == dev->dev_tag) && + (map->idx == dev->idx)) { + soc_clk_enable((clk_module_t)map->module); ///< TODO:打开时钟 + break; + } + + map++; + } +} + +void csi_clk_disable(csi_dev_t *dev) +{ + csi_clkmap_t *map = clk_map; + + while (map->module != 0xFFFFFFFFU) { + if ((map->dev_tag == dev->dev_tag) && + (map->idx == dev->idx)) { + soc_clk_disable((clk_module_t)map->module); ///< TODO:关闭时钟 + break; + } + + map++; + } +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/codec.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/codec.c new file mode 100644 index 00000000000..3a99cdb7de0 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/codec.c @@ -0,0 +1,784 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include "es7210.h" +#include "es8156.h" +#include "es_port.h" + +extern uint16_t i2s_tx_hs_num[]; +extern uint16_t i2s_rx_hs_num[]; + +static csi_i2s_t i2s_codec_output; +static csi_i2s_t i2s_codec_input; +static csi_i2s_t i2s_mclk; + +es7210_dev_t es7210_dev; +es8156_dev_t es8156_dev; + +#define INPUT_I2S_IDX 4U +#define OUTPUT_I2S_IDX 1U + +static void es_codec_irq(csi_i2s_t *i2s, csi_i2s_event_t event, void *arg) +{ + csi_codec_t *codec_cb = (csi_codec_t *) arg; + + if (event == I2S_EVENT_RECEIVE_COMPLETE) { + if (codec_cb->input_chs->callback) { + codec_cb->input_chs->callback(codec_cb->input_chs, CODEC_EVENT_PERIOD_READ_COMPLETE, codec_cb->input_chs->arg); + } + } else if (event == I2S_EVENT_SEND_COMPLETE) { + if (codec_cb->output_chs->callback) { + codec_cb->output_chs->callback(codec_cb->output_chs, CODEC_EVENT_PERIOD_WRITE_COMPLETE, codec_cb->output_chs->arg); + } + } else if (event == I2S_EVENT_ERROR) { + if (i2s->dev.idx == OUTPUT_I2S_IDX) { + if (codec_cb->output_chs->callback) { + codec_cb->output_chs->callback(codec_cb->output_chs, CODEC_EVENT_ERROR, codec_cb->output_chs->arg); + } + } else if (i2s->dev.idx == INPUT_I2S_IDX) { + if (codec_cb->input_chs->callback) { + codec_cb->input_chs->callback(codec_cb->input_chs, CODEC_EVENT_ERROR, codec_cb->input_chs->arg); + } + } + } else if (event == I2S_EVENT_TX_BUFFER_EMPTY) { + if (i2s->dev.idx == OUTPUT_I2S_IDX) { + if (codec_cb->output_chs->callback) { + codec_cb->output_chs->callback(codec_cb->output_chs, CODEC_EVENT_WRITE_BUFFER_EMPTY, codec_cb->output_chs->arg); + } + } + } else if (event == I2S_EVENT_RX_BUFFER_FULL) { + if (i2s->dev.idx == INPUT_I2S_IDX) { + if (codec_cb->input_chs->callback) { + codec_cb->input_chs->callback(codec_cb->input_chs, CODEC_EVENT_READ_BUFFER_FULL, codec_cb->input_chs->arg); + } + } + } + +} + +/** + \brief Init the codec according to the specified + \param[in] codec codec handle to operate. + \param[in] idx codec interface idx + \return error code +*/ +csi_error_t csi_codec_init(csi_codec_t *codec, uint32_t idx) +{ + CSI_PARAM_CHK(codec, CSI_ERROR); + csi_error_t ret = CSI_OK; + csi_i2s_format_t i2s_format; + /* adc i2s0 pinmux init */ + csi_pin_set_mux(PA10, PA10_I2S0_MCLK); + /* DAC i2s1 pinmux init */ + csi_pin_set_mux(PA2, PA2_I2S1_SCLK); + csi_pin_set_mux(PA3, PA3_I2S1_WSCLK); + csi_pin_set_mux(PA5, PA5_I2S1_SDA); + csi_pin_set_mux(PA26, PA26_I2S1_MCLK); + + es_port_iic_init(); + + ret = csi_i2s_init(&i2s_codec_output, OUTPUT_I2S_IDX); ///< init output i2s + csi_i2s_attach_callback(&i2s_codec_output, es_codec_irq, (void *)codec); + csi_i2s_enable(&i2s_codec_output, false); + i2s_format.mode = I2S_MODE_MASTER; + i2s_format.protocol = I2S_PROTOCOL_I2S; + i2s_format.width = I2S_SAMPLE_WIDTH_16BIT; + i2s_format.rate = I2S_SAMPLE_RATE_48000; + i2s_format.polarity = I2S_LEFT_POLARITY_LOW; + csi_i2s_format(&i2s_codec_output, &i2s_format); + + ret = csi_i2s_init(&i2s_codec_input, INPUT_I2S_IDX); ///< init input i2s + csi_i2s_attach_callback(&i2s_codec_input, es_codec_irq, (void *)codec); + i2s_format.mode = I2S_MODE_MASTER; + i2s_format.protocol = I2S_PROTOCOL_I2S; + i2s_format.width = I2S_SAMPLE_WIDTH_16BIT; + i2s_format.rate = I2S_SAMPLE_RATE_48000; + i2s_format.polarity = I2S_LEFT_POLARITY_LOW; + csi_i2s_format(&i2s_codec_input, &i2s_format); + + ret = csi_i2s_init(&i2s_mclk, 0); ///< init input i2s + csi_i2s_attach_callback(&i2s_mclk, es_codec_irq, (void *)codec); + i2s_format.mode = I2S_MODE_MASTER; + i2s_format.protocol = I2S_PROTOCOL_I2S; + i2s_format.width = I2S_SAMPLE_WIDTH_16BIT; + i2s_format.rate = I2S_SAMPLE_RATE_8000; + i2s_format.polarity = I2S_LEFT_POLARITY_LOW; + csi_i2s_format(&i2s_mclk, &i2s_format); + csi_i2s_enable(&i2s_mclk,true); + + return ret; +} + +/** + \brief codec uninit + \param[in] codec codec handle to operate. + \return none +*/ +void csi_codec_uninit(csi_codec_t *codec) +{ + CSI_PARAM_CHK_NORETVAL(codec); + return; +} + +/** + \brief Open a codec output channel + \param[in] codec codec handle to operate. + \param[in] ch codec output channel handle. + \param[in] ch_idx codec output channel idx. + \return error code +*/ +csi_error_t csi_codec_output_open(csi_codec_t *codec, csi_codec_output_t *ch, uint32_t ch_idx) +{ + CSI_PARAM_CHK(codec, CSI_ERROR); + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_OK; + codec->output_chs = ch; + ch->state.error = 0U; + ch->state.readable = 0U; + ch->state.writeable = 0U; + ch->callback = NULL; + return ret; +} + +/** + \brief Config codec output channel + \param[in] ch codec output channel handle. + \param[in] config codec channel prarm. + \return error code +*/ +csi_error_t csi_codec_output_config(csi_codec_output_t *ch, csi_codec_output_config_t *config) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + CSI_PARAM_CHK(config, CSI_ERROR); + csi_error_t ret = CSI_OK; + csi_i2s_format_t i2s_format; + + es8156_config_t es8156_config; + es8156_config.data_len = ES8156_16BIT_LENGTH; + es8156_config.i2s_mode = ES8156_I2S_MODE_SLAVE; + es8156_config.i2s_protocol = ES8156_NORMAL_I2S; + es8156_config.i2s_sclk_freq = ES8156_I2S_SCLK_32FS; + es8156_config.mclk_freq = ES8156_MCLK_256FS; + es8156_config.i2s_rate = ES8156_I2S_SAMPLE_RATE_48000; + + es8156_dev.es8156_iic_read = es_port_iic_read; + es8156_dev.es8156_iic_write = es_port_iic_write; + es8156_dev.es8156_addr = 0x9U; + + es8156_init(&es8156_dev, &es8156_config); + + ch->ring_buf->buffer = config->buffer; + ch->ring_buf->size = config->buffer_size; + ch->period = config->period; + ch->sound_channel_num = config->sound_channel_num; + + if (i2s_codec_output.dev.reg_base == 0U) { + ret = CSI_ERROR; + } else { + csi_i2s_enable(&i2s_codec_output, false); + i2s_format.mode = I2S_MODE_MASTER; + i2s_format.protocol = I2S_PROTOCOL_I2S; + i2s_format.width = (csi_i2s_sample_width_t)config->bit_width; + i2s_format.rate = (csi_i2s_sample_rate_t)config->sample_rate; + i2s_format.polarity = I2S_LEFT_POLARITY_LOW; + csi_i2s_format(&i2s_codec_output, &i2s_format); + + csi_i2s_tx_set_buffer(&i2s_codec_output, ch->ring_buf); + csi_i2s_tx_buffer_reset(&i2s_codec_output); + ret = csi_i2s_tx_set_period(&i2s_codec_output, ch->period); + } + + return ret; +} + +/** + \brief Attach the callback handler to codec output + \param[in] ch codec output channel handle. + \param[in] cb callback function + \param[in] arg user can define it by himself as callback's param + \return error code +*/ +csi_error_t csi_codec_output_attach_callback(csi_codec_output_t *ch, void *callback, void *arg) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_OK; + ch->callback = callback; + ch->arg = arg; + return ret; +} + +/** + \brief detach the callback handler + \param[in] ch codec output channel handle. + \return none +*/ +void csi_codec_output_detach_callback(csi_codec_output_t *ch) +{ + CSI_PARAM_CHK_NORETVAL(ch); + ch->callback = NULL; + ch->arg = NULL; + csi_i2s_detach_callback(&i2s_codec_output); +} + +/** + \brief Close a CODEC output channel + \param[in] ch codec output channel handle. + \return error code +*/ +void csi_codec_output_close(csi_codec_output_t *ch) +{ + CSI_PARAM_CHK_NORETVAL(ch); + ch->state.writeable = 0U; + ch->state.readable = 0U; + ch->state.error = 0U; + csi_i2s_uninit(&i2s_codec_output); +} + +/** + \brief link DMA channel to codec output channel + \param[in] ch codec output channel handle. + \param[in] dma dma channel info. + \return error code +*/ +csi_error_t csi_codec_output_link_dma(csi_codec_output_t *ch, csi_dma_ch_t *dma) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_OK; + ch->dma = dma; + ret = csi_i2s_tx_link_dma(&i2s_codec_output, dma); + return ret; +} + +/** + \brief write an amount of data to cache in blocking mode. + \param[in] ch the codec output channel + \param[in] data send data. + \param[in] size receive data size. + \return The num of data witch is send successful +*/ +uint32_t csi_codec_output_write(csi_codec_output_t *ch, const void *data, uint32_t size) +{ + return csi_i2s_send(&i2s_codec_output, data, size); +} + +/** + \brief Write data to the cache. + \With asynchronous sending, + \the data is first written to the cache and then output through the codec interface. + \This function does not block, and the return value is the number + \of data that was successfully written to the cache. + \param[in] ch the codec output channel + \param[in] data send data. + \param[in] size receive data size. + \return The data size that write to cache +*/ +uint32_t csi_codec_output_write_async(csi_codec_output_t *ch, const void *data, uint32_t size) +{ + return csi_i2s_send_async(&i2s_codec_output, data, size); +} + +/** + \brief Start sending data from the cache + \param[in] ch codec output channel handle. + \return error code +*/ +csi_error_t csi_codec_output_start(csi_codec_output_t *ch) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + ch->state.writeable = 1U; + return csi_i2s_send_start(&i2s_codec_output); +} + +/** + \brief Stop sending data from the cache + \param[in] ch codec output channel handle. + \return error code +*/ +void csi_codec_output_stop(csi_codec_output_t *ch) +{ + CSI_PARAM_CHK_NORETVAL(ch); + ch->state.writeable = 0U; + csi_i2s_send_stop(&i2s_codec_output); +} + +/** + \brief Pause sending data from the cache + \param[in] ch codec output channel handle. + \return error code +*/ +csi_error_t csi_codec_output_pause(csi_codec_output_t *ch) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + ch->state.writeable = 0U; + return csi_i2s_send_pause(&i2s_codec_output); +} + +/** + \brief Resume sending data from the cache + \param[in] ch codec output channel handle. + \return error code +*/ +csi_error_t csi_codec_output_resume(csi_codec_output_t *ch) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + ch->state.writeable = 1U; + return csi_i2s_send_resume(&i2s_codec_output); +} + +/** + \brief Get cache free space + \param[in] ch codec output channel handle. + \return buffer free space (bytes) +*/ +uint32_t csi_codec_output_buffer_avail(csi_codec_output_t *ch) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + return csi_ringbuf_avail(ch->ring_buf); +} + +/** + \brief Get buffer data num + \param[in] ch Codec output channel handle + \return Buffer free space (bytes) +*/ +uint32_t csi_codec_output_buffer_remain(csi_codec_output_t *ch) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + return csi_ringbuf_len(ch->ring_buf); +} + +/** + \brief Reset the buf, discard all data in the cache + \param[in] ch codec output channel handle. + \return error code +*/ +csi_error_t csi_codec_output_buffer_reset(csi_codec_output_t *ch) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_ERROR; + csi_ringbuf_reset(ch->ring_buf); + + if (ch->ring_buf->buffer != NULL) { + memset(ch->ring_buf->buffer, 0, ch->ring_buf->size); + } + + if ((ch->ring_buf->read == 0U) && (ch->ring_buf->write == 0U)) { + ret = CSI_OK; + } + + return ret; +} + +/** + \brief mute codec ouput channel + \param[in] ch codec output channel handle. + \param[in] en true codec mute. + \return error code +*/ +csi_error_t csi_codec_output_mute(csi_codec_output_t *ch, bool enable) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_OK; + es8156_set_software_mute(&es8156_dev, true); + return ret; +} + +/** + \brief Set codec ouput channel digital gain. + \param[in] ch codec output channel handle. + \param[in] val gain val. + \return error code +*/ +csi_error_t csi_codec_output_digital_gain(csi_codec_output_t *ch, uint32_t val) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_UNSUPPORTED; + return ret; +} + +/** + \brief Set codec ouput channel analog gain. + \param[in] ch codec output channel handle. + \param[in] val gain val. + \return error code +*/ +csi_error_t csi_codec_output_analog_gain(csi_codec_output_t *ch, uint32_t val) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_OK; + + /* + range0 ~ 0xff, step:0.75DB + 0(-95.5DB)... 0xbf(0DB) ... 0xff(32DB) + */ + if (val > 0xff) { + val = 0xff; + } + + ret = es8156_set_volume(&es8156_dev, val); + + return ret; +} + +/** + \brief Set codec ouput channel mix gain. + \param[in] ch codec output channel handle. + \param[in] val gain val. + \return error code +*/ +csi_error_t csi_codec_output_mix_gain(csi_codec_output_t *ch, uint32_t val) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_UNSUPPORTED; + return ret; +} + +/** + \brief Get codec output channel state. + \param[in] ch codec output channel handle. + \param[out] state channel state. + \return channel state +*/ +csi_error_t csi_codec_output_get_state(csi_codec_output_t *ch, csi_state_t *state) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + CSI_PARAM_CHK(state, CSI_ERROR); + csi_error_t ret = CSI_OK; + memcpy(state, &(ch->state), sizeof(csi_state_t)); + return ret; +} + +/** + \brief Open a CODEC input channel + \param[in] codec codec handle to operate. + \param[in] ch codec input channel handle. + \param[in] ch_idx codec input channel idx. + \return error code +*/ +csi_error_t csi_codec_input_open(csi_codec_t *codec, csi_codec_input_t *ch, uint32_t ch_idx) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + CSI_PARAM_CHK(codec, CSI_ERROR); + csi_error_t ret = CSI_OK; + codec->input_chs = ch; + ch->state.error = 0U; + ch->state.readable = 0U; + ch->state.writeable = 0U; + ch->callback = NULL; + return ret; +} + +/** + \brief Config codec input channel + \param[in] ch codec input channel handle. + \param[in] config codec channel prarm. + \return error code +*/ +csi_error_t csi_codec_input_config(csi_codec_input_t *ch, csi_codec_input_config_t *config) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + CSI_PARAM_CHK(config, CSI_ERROR); + csi_error_t ret = CSI_OK; + csi_i2s_format_t i2s_format; + es7210_config_t es7210_config; + + ch->ring_buf->buffer = config->buffer; + ch->ring_buf->size = config->buffer_size; + ch->period = config->period; + ch->sound_channel_num = config->sound_channel_num; + + es7210_config.data_len = ES7210_16BIT_LENGTH; + es7210_config.i2s_mode = ES7210_I2S_MODE_SLAVE; + es7210_config.i2s_protocol = ES7210_NORMAL_I2S; + es7210_config.i2s_sclk_freq = ES7210_I2S_SCLK_32FS; + es7210_config.mclk_freq = ES7210_MCLK_256FS; + + es7210_dev.es7210_iic_read = es_port_iic_read; + es7210_dev.es7210_iic_write = es_port_iic_write; + es7210_dev.es7210_addr = 0x40U; + + es7210_init(&es7210_dev, &es7210_config); + + if (i2s_codec_input.dev.reg_base == 0U) { + ret = CSI_ERROR; + } else { + csi_i2s_enable(&i2s_codec_input, false); + + i2s_format.mode = I2S_MODE_MASTER; + i2s_format.protocol = I2S_PROTOCOL_I2S; + i2s_format.width = (csi_i2s_sample_width_t)config->bit_width; + i2s_format.rate = (csi_i2s_sample_rate_t)config->sample_rate; + i2s_format.polarity = I2S_LEFT_POLARITY_LOW; + i2s_format.sclk_nfs = I2S_SCLK_32FS; + i2s_format.mclk_nfs = I2S_MCLK_256FS; + csi_i2s_format(&i2s_codec_input, &i2s_format); + + csi_i2s_rx_set_buffer(&i2s_codec_input, ch->ring_buf); + csi_i2s_rx_buffer_reset(&i2s_codec_input); + ret = csi_i2s_rx_set_period(&i2s_codec_input, ch->period); + } + + return ret; +} + +/** + \brief Attach the callback handler to codec output + \param[in] ch codec input channel handle. + \param[in] cb callback function + \param[in] arg user can define it by himself as callback's param + \return error code +*/ +csi_error_t csi_codec_input_attach_callback(csi_codec_input_t *ch, void *callback, void *arg) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_OK; + ch->callback = callback; + ch->arg = arg; + return ret; +} + +/** + \brief detach the callback handler + \param[in] ch codec input channel handle. + \return none +*/ +void csi_codec_input_detach_callback(csi_codec_input_t *ch) +{ + CSI_PARAM_CHK_NORETVAL(ch); + ch->callback = NULL; + ch->arg = NULL; + csi_i2s_detach_callback(&i2s_codec_input); +} + +/** + \brief Close a CODEC input channel + \param[in] ch codec input channel handle.. + \return error code +*/ +void csi_codec_input_close(csi_codec_input_t *ch) +{ + CSI_PARAM_CHK_NORETVAL(ch); + ch->state.writeable = 0U; + ch->state.readable = 0U; + ch->state.error = 0U; + csi_i2s_uninit(&i2s_codec_input); +} + +/** + \brief link DMA channel to codec input channel + \param[in] ch codec input channel handle. + \param[in] dma dma channel info. + \return error code +*/ +csi_error_t csi_codec_input_link_dma(csi_codec_input_t *ch, csi_dma_ch_t *dma) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_OK; + ch->dma = dma; + ret = csi_i2s_rx_link_dma(&i2s_codec_input, dma); + return ret; +} + +/** + \brief read an amount of data in blocking mode. + \param[in] ch codec input channel handle. + \param[in] data save receive data. + \param[in] size receive data size. + \return The size of data receive successfully +*/ +uint32_t csi_codec_input_read(csi_codec_input_t *ch, void *data, uint32_t size) +{ + return csi_i2s_receive(&i2s_codec_input, data, size); +} + +/** + \brief Read data from the cache. + \Using asynchronous receive. + \This function read data from the cache, returns the number of successful reads, + \and returns 0 if there is no data in the cache. + \param[in] ch codec input channel handle. + \param[in] data the buf save receive data. + \param[in] size receive data size. + \return The size of data read successfully +*/ +uint32_t csi_codec_input_read_async(csi_codec_input_t *ch, void *data, uint32_t size) +{ + return csi_i2s_receive_async(&i2s_codec_input, data, size); +} + +/** + \brief Start receive data, writes the recording data to the cache + \param[in] ch codec input channel handle. + \return error code +*/ +csi_error_t csi_codec_input_start(csi_codec_input_t *ch) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + ch->state.readable = 1U; + return csi_i2s_receive_start(&i2s_codec_input); +} + +/** + \brief Stop receive data. + \param[in] ch codec input channel handle. + \return error code +*/ +void csi_codec_input_stop(csi_codec_input_t *ch) +{ + CSI_PARAM_CHK_NORETVAL(ch); + ch->state.readable = 0U; + csi_i2s_receive_stop(&i2s_codec_input); +} + +/** + \brief Get buffer free space + \param[in] ch Codec input channel handle + \return Buffer free space (bytes) +*/ +uint32_t csi_codec_input_buffer_avail(csi_codec_input_t *ch) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + return csi_ringbuf_avail(ch->ring_buf); +} + +/** + \brief Get buffer data num + \param[in] ch Codec input channel handle + \return Buffer free space (bytes) +*/ +uint32_t csi_codec_input_buffer_remain(csi_codec_input_t *ch) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + return csi_ringbuf_len(ch->ring_buf); +} + +/** + \brief Reset the buf, discard all data in the cache + \param[in] ch codec input channel handle. + \return error code +*/ +csi_error_t csi_codec_input_buffer_reset(csi_codec_input_t *ch) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_ERROR; + csi_ringbuf_reset(ch->ring_buf); + + if (ch->ring_buf->buffer != NULL) { + memset(ch->ring_buf->buffer, 0, ch->ring_buf->size); + } + + if ((ch->ring_buf->read == 0U) && (ch->ring_buf->write == 0U)) { + ret = CSI_OK; + } + + return ret; +} + +/** + \brief mute codec input channel + \param[in] ch codec input channel handle. + \param[in] en true codec mute. + \return error code +*/ +csi_error_t csi_codec_input_mute(csi_codec_input_t *ch, bool en) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_OK; + es7210_mic1_set_mute(&es7210_dev, en); + es7210_mic2_set_mute(&es7210_dev, en); + return ret; +} + +/** + \brief Set codec input channel digital gain. + \param[in] ch codec input channel handle. + \param[in] val gain val. + \return error code +*/ +csi_error_t csi_codec_input_digital_gain(csi_codec_input_t *ch, uint32_t val) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_UNSUPPORTED; + return ret; +} + +/** + \brief Set codec input channel analog gain. + \param[in] ch codec input channel handle. + \param[in] val gain val. + \return error code +*/ +csi_error_t csi_codec_input_analog_gain(csi_codec_input_t *ch, uint32_t val) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_OK; + + /* + range0 ~ 14, step:3DB + 0(-95.5DBDB)... 0xBF(0DB) ... 0xff(32DB) + */ + if (val > 0xff) { + val = 0xff; + } + + ret = es7210_adc1_set_gain(&es7210_dev, val); + ret = es7210_adc2_set_gain(&es7210_dev, val); + ret = es7210_adc3_set_gain(&es7210_dev, val); + ret = es7210_adc4_set_gain(&es7210_dev, val); + return ret; +} + +/** + \brief Set codec input channel mix gain. + \param[in] ch codec input channel handle. + \param[in] val gain val. + \return error code +*/ +csi_error_t csi_codec_input_mix_gain(csi_codec_input_t *ch, uint32_t val) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + csi_error_t ret = CSI_UNSUPPORTED; + return ret; +} + +/** + \brief Get codec input channel state. + \param[in] ch codec input channel handle. + \param[out] state channel state. + \return channel state +*/ +csi_error_t csi_codec_input_get_state(csi_codec_input_t *ch, csi_state_t *state) +{ + CSI_PARAM_CHK(ch, CSI_ERROR); + CSI_PARAM_CHK(state, CSI_ERROR); + csi_error_t ret = CSI_OK; + memcpy(state, &(ch->state), sizeof(csi_state_t)); + return ret; +} + + + + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/crc.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/crc.c new file mode 100644 index 00000000000..6c15756eda0 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/crc.c @@ -0,0 +1,455 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file crc.c + * @brief CSI Source File for CRC Driver + * @version V1.0 + * @date 19. Feb 2020 + ******************************************************************************/ +#include +#include +#include +#include +#include +#include + +/** +\brief CRC State +*/ +typedef struct { + uint32_t busy : 1; ///< busy flag + uint32_t timeout : 1; ///< timeout state + uint32_t error : 1; ///< error +} csi_crc_state_t; + +/*----- CRC Control Codes: Mode -----*/ +typedef enum { + CRC_MODE_CRC8 = 0, ///< Mode CRC8 + CRC_MODE_CRC16, ///< Mode CRC16 + CRC_MODE_CRC32 ///< Mode CRC32 +} csi_crc_mode_t; + + +/*----- CRC Control Codes: Mode Parameters: Key length -----*/ +typedef enum { + CRC_STANDARD_ROHC = 0, ///< Standard CRC RHOC + CRC_STANDARD_MAXIM, ///< Standard CRC MAXIAM + CRC_STANDARD_X25, ///< Standard CRC X25 + CRC_STANDARD_CCITT, ///< Standard CRC CCITT + CRC_STANDARD_CCITT_FALSE, ///< Standard CRC CCITT-FALSE + CRC_STANDARD_USB, ///< Standard CRC USB + CRC_STANDARD_IBM, ///< Standard CRC IBM + CRC_STANDARD_MODBUS, ///< Standard CRC MODBUS + CRC_STANDARD_ITU, ///< Standard CRC ITU + CRC_STANDARD_PMEQ_2, ///< Standard CRC PMEQ_2 + CRC_STANDARD_XMODEM, ///< Standard CRC XMODEM + CRC_STANDARD_DNP, ///< Standard CRC DNP + CRC_STANDARD_NONE, ///< Standard CRC NONE + CRC_STANDARD_CRC8_31, + CRC_STANDARD_CRC8_7, +} csi_crc_standard_t; + +/** +\brief CRC config param + */ +typedef struct { + csi_crc_mode_t mode; + csi_crc_standard_t standard; +} csi_crc_config_t; + +/** +\brief CRC ctrl block + */ +typedef struct { + csi_dev_t dev; + csi_crc_config_t config; + csi_crc_state_t state; +} csi_crc_t; + +/** + \brief Initialize CRC Interface. 1. Initializes the resources needed for the CRC interface 2.registers event callback function + \param[in] crc crc handle to operate. + \param[in] idx device id + \return \ref csi_error_t +*/ +csi_error_t csi_crc_init(csi_crc_t *crc, uint32_t idx) +{ + CSI_PARAM_CHK(crc, CSI_ERROR); + ///< 获取中断号、基地址等相关信息 + target_get(DEV_WJ_CRC_TAG, idx, &crc->dev); + + return CSI_OK; +} + +/** + \brief De-initialize CRC Interface. stops operation and releases the software resources used by the interface + \param[in] crc crc handle to operate. + \return none +*/ +void csi_crc_uninit(csi_crc_t *crc) +{ + +} +/** + \brief config crc mode. + \param[in] crc crc handle to operate. + \param[in] config \ref csi_crc_config_t + \return \ref csi_error_t +*/ +csi_error_t csi_crc_config(csi_crc_t *crc, csi_crc_config_t *config) +{ + csi_error_t ret = CSI_OK; + CSI_PARAM_CHK(crc, CSI_ERROR); + + crc->config = *config; + + switch (config->standard) { + case CRC_STANDARD_MODBUS: + ///< TODO:设置模式 + ///< TODO:设置极性 + ///< TODO:设置初始值 + + break; + + case CRC_STANDARD_IBM: + + ///< TODO:设置模式 + ///< TODO:设置极性 + ///< TODO:设置初始值 + break; + + case CRC_STANDARD_MAXIM: + ///< TODO:设置模式 + ///< TODO:设置极性 + ///< TODO:设置初始值 + break; + + case CRC_STANDARD_USB: + ///< TODO:设置模式 + ///< TODO:设置极性 + ///< TODO:设置初始值 + break; + + case CRC_STANDARD_CCITT: + ///< TODO:设置模式 + ///< TODO:设置极性 + ///< TODO:设置初始值 + break; + + case CRC_STANDARD_CCITT_FALSE: + ret = CSI_ERROR; + break; + + case CRC_STANDARD_X25: + ///< TODO:设置模式 + ///< TODO:设置极性 + ///< TODO:设置初始值 + break; + + case CRC_STANDARD_CRC8_31: + ///< TODO:设置模式 + ///< TODO:设置极性 + break; + + case CRC_STANDARD_CRC8_7: + ///< TODO:设置模式 + ///< TODO:设置极性 + break; + + + case CRC_STANDARD_XMODEM: + ret = CSI_ERROR; + break; + + + case CRC_STANDARD_DNP: + ret = CSI_ERROR; + break; + + default: + ret = CSI_ERROR; + } + + return ret; + +} + +/** + \brief accumulate crc. Computes the 32-bit CRC of 32-bit data buffer using combination of the previous CRC value and the new one. + \param[in] crc crc handle to operate. + \param[in] data Pointer to the input data + \param[in] size intput data size. + \return \ref calculate value +*/ +uint32_t csi_crc_accumulate(csi_crc_t *crc, const void *data, uint32_t size) +{ + uint32_t ret = 0U; + CSI_PARAM_CHK(crc, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + + if (size <= 0U) { + ret = 0U; + } else { + + crc->state.busy = 1U; + + /* put the data int the register */ + uint32_t cur; + uint8_t *p = (uint8_t *)data; + + for (cur = 0U; cur < (size - 3U); cur += 4U, p += 4U) { + ///< TODO:设置待计算crc 数据: (uint32_t)(p[0]) | ((uint32_t)(p[1]) << 8U) | ((uint32_t)(p[2]) << 16U) | ((uint32_t)(p[3]) << 24U) + } + + uint32_t data1 = 0U; + uint8_t i; + + if (cur < size) { + for (i = 0U; i < (size - cur); i++) { + data1 |= ((uint32_t)(p[i]) << (i * 8U)); + } + ///< TODO:设置待计算crc 数据 : data1 + } + + crc->state.busy = 0U; + ///< TODO:获取计算结果到ret + } + + return ret; + +} + +/** + \brief calculate crc. Computes the 32-bit CRC of 32-bit data buffer independently of the previous CRC value. + \param[in] crc crc handle to operate. + \param[in] data Pointer to the input data + \param[in] size intput data size. + \return \ref calculate value +*/ +uint32_t csi_crc_calculate(csi_crc_t *crc, const void *data, uint32_t size) +{ + uint32_t ret = 0U; + + CSI_PARAM_CHK(crc, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + + if (size <= 0U) { + ret = 0U; + } else { + + crc->state.busy = 1U; + /* put the data int the register */ + uint32_t cur; + uint8_t *p = (uint8_t *)data; + + for (cur = 0U; cur < (size - 3U); cur += 4U, p += 4U) { + ///< TODO:设置待计算crc 数据: (uint32_t)(p[0]) | ((uint32_t)(p[1]) << 8U) | ((uint32_t)(p[2]) << 16U) | ((uint32_t)(p[3]) << 24U) + } + + uint32_t data1 = 0U; + uint8_t i; + + if (cur < size) { + for (i = 0U; i < (size - cur); i++) { + data1 |= ((uint32_t)(p[i]) << (i * 8U)); + } + + ///< TODO:设置待计算crc 数据 : data1 + } + + crc->state.busy = 0U; + + ///< TODO:获取计算结果到ret + } + + return ret; +} + +/** + \brief Get CRC state. + \param[in] crc crc handle to operate. + \return CRC state \ref csi_crc_state_t +*/ +csi_crc_state_t csi_crc_get_state(csi_crc_t *crc) +{ + + return crc->state; +} + +/** + * \brief Compute the CRC-7 checksum of a buffer. + * + * See JESD84-A441. Used by the MMC protocol. Uses 0x09 as the + * polynomial with no reflection. The CRC is left + * justified, so bit 7 of the result is bit 6 of the CRC. + * init = 0; poly = 0x09 refin = 0 refout = 0 xorout = 0 + * \param[in] crc crc init value or crc immediate result + * \param[in] data data buf to be calculate + * \param[in] size data size + * + * \return The computed CRC7 value + */ +uint8_t csi_crc7_be(uint8_t crc, uint8_t *data, uint32_t size) +{ + return 0; +} + +/** + * \brief Compute the CRC-8 checksum of a buffer. + * init = 0 or 0xff; poly = 0x07 refin = 0 refout = 0 xorout = 0 + * \param[in] crc crc init value or crc immediate result + * \param[in] data data buf to be calculate + * \param[in] size data size + * \return The computed CRC8 value + */ +uint8_t csi_crc8(uint8_t crc, uint8_t *data, size_t size) +{ + csi_crc_state_t status; + csi_crc_config_t config; + static csi_crc_t crc1; + uint8_t out; + + status.busy = 1U; + + csi_crc_init(&crc1, 0U); + + config.mode = CRC_MODE_CRC8; + config.standard = CRC_STANDARD_CRC8_7; + + csi_crc_config(&crc1, &config); + ///< TODO:设置初始值:crc + out = (uint16_t)(csi_crc_calculate(&crc1, data, size)); + + while (status.busy == 1U) { + status = csi_crc_get_state(&crc1); + } + + csi_crc_uninit(&crc1); + return out; +} + +/** + * \brief Compute the CRC-8 checksum of a buffer. + * init = 0; poly = 0x31 refin = 1 refout = 1 xorout = 0 + * \param[in] crc crc init value or crc immediate result + * \param[in] data data buf to be calculate + * \param[in] size data size + * \return The computed CRC8 value + */ +uint8_t csi_crc8_maxim(uint8_t crc, uint8_t *data, size_t size) +{ + csi_crc_state_t status; + csi_crc_config_t config; + static csi_crc_t crc1; + uint8_t out; + + status.busy = 1U; + + csi_crc_init(&crc1, 0U); + + config.mode = CRC_MODE_CRC8; + config.standard = CRC_STANDARD_CRC8_31; + csi_crc_config(&crc1, &config); + ///< TODO:设置初始值:crc + out = (uint16_t)(csi_crc_calculate(&crc1, data, size)); + + while (status.busy == 1U) { + status = csi_crc_get_state(&crc1); + } + + csi_crc_uninit(&crc1); + return out; + +} + +/** + * \brief Compute the CRC-16 checksum of a buffer. + * init = 0 or 0xffff; poly = 0x8005 refin = 1 refout = 1 xorout = 0 + * \param[in] crc crc init value or crc immediate result + * \param[in] data data buf to be calculate + * \param[in] size data size + * \return The computed CRC16 without xorout + */ +uint16_t csi_crc16(uint16_t crc, uint8_t *data, uint32_t size) +{ + csi_crc_state_t status; + csi_crc_t crc1; + csi_crc_config_t config; + uint16_t out; + status.busy = 1U; + + if ((crc == 0U) || (crc == 0xffffU)) { + + csi_crc_init(&crc1, 0U); + + config.mode = CRC_MODE_CRC16; + + if (crc == 0xffffU) { + config.standard = CRC_STANDARD_MODBUS; + } else { + config.standard = CRC_STANDARD_IBM; + } + + csi_crc_config(&crc1, &config); + out = (uint16_t)(csi_crc_calculate(&crc1, data, size)); + + while (status.busy == 1U) { + status = csi_crc_get_state(&crc1); + } + + csi_crc_uninit(&crc1); + } else { + out = 0U; /* code */ + + } + + return out; +} + +/** + * \brief Compute the CRC-16 checksum of a buffer. + * init = 0; poly = 0x1021 refin = 1 refout = 1 xorout = 0 + * \param[in] crc crc init value or crc immediate result + * \param[in] data data buf to be calculate + * \param[in] size data size + * \return The computed CRC16 without xorout + */ +uint16_t csi_crc16_ccitt(uint16_t crc, uint8_t *data, uint32_t size) +{ + csi_crc_state_t status; + csi_crc_config_t config; + static csi_crc_t crc1; + uint16_t out; + + status.busy = 1U; + + csi_crc_init(&crc1, 0U); + config.mode = CRC_MODE_CRC16; + config.standard = CRC_STANDARD_CCITT; + csi_crc_config(&crc1, &config); + out = (uint16_t)(csi_crc_calculate(&crc1, data, size)); + + while (status.busy == 1U) { + status = csi_crc_get_state(&crc1); + } + + csi_crc_uninit(&crc1); + + return out; +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/dma.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/dma.c new file mode 100644 index 00000000000..47d5c6657ec --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/dma.c @@ -0,0 +1,383 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file dw_dma.c + * @brief CSI Source File for uart Driver + * @version V1.0 + * @date 16. Mar 2020 + * @vendor csky + * @name dw_dma + * @ip_id 0x111000010 + * @model dma + * @tag DEV_DW_DMA_TAG + ******************************************************************************/ + +#include +#include +#include + +#define CONFIG_DMA_CHANNEL_NUM 8 + +extern uint8_t g_dma_chnum[]; +csi_dma_t *dma_array[2] = {0}; +static uint32_t inited_ctrl_num = 0U; + +void dw_dma_irq_handler(void *arg) +{ + + ///< TODO:获取中断状态 + ///< TODO:清除中断 + ///< TODO:处理中断 +} + +csi_error_t csi_dma_init(csi_dma_t *dma, int8_t ctrl_id) +{ + CSI_PARAM_CHK(dma, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< 获取中断号、基地址等相关信息 + ret = target_get(DEV_DW_DMA_TAG, (uint32_t) ctrl_id, &dma->dev); + + if (ret == CSI_OK) { + + slist_init(&dma->head); + dma->alloc_status = 0U; + dma_array[ctrl_id] = dma; + dma_array[ctrl_id]->ch_num = g_dma_chnum[ctrl_id]; + + if (ctrl_id == 0) { + + ///< TODO:清除DMA0搬运中断 + ///< TODO:清除DMA0块搬运中断 + ///< TODO:清除DMA0错误中断 + ///< TODO:清除DMA0源搬运中断 + ///< TODO:清除DMA0目的搬运中断 + + } else if (ctrl_id == 1) { + + ///< TODO:清除DMA1搬运中断 + ///< TODO:清除DMA1块搬运中断 + ///< TODO:清除DMA1错误中断 + ///< TODO:清除DMA1源搬运中断 + ///< TODO:清除DMA1目的搬运中断 + + } + + ///< 注册DMA中断服务函数,使能中断控制器中对应的中断 + csi_irq_attach((uint32_t)dma->dev.irq_num, &dw_dma_irq_handler, &dma->dev); + csi_irq_enable((uint32_t)dma->dev.irq_num); + + if (ctrl_id == 0) { + ///< TODO:关闭DMA0所有通道的使能 + } else if (ctrl_id == 1) { + ///< TODO:关闭DMA1所有通道的使能 + } + + ///< TODO:使能DMA控制器 + + uint32_t result = csi_irq_save(); + inited_ctrl_num++; + csi_irq_restore(result); + } + + return ret; +} + +void csi_dma_uninit(csi_dma_t *dma) +{ + CSI_PARAM_CHK_NORETVAL(dma); + slist_init(&dma->head); + dma->alloc_status = 0U; + dma_array[dma->dev.idx] = NULL; + ///< 禁止中断控制器对应的中断,注销DMA中断服务函数 + csi_irq_disable((uint32_t)dma->dev.irq_num); + csi_irq_detach((uint32_t)dma->dev.irq_num); + + ///< TODO:关闭DMA控制器 + + uint32_t result = csi_irq_save(); + inited_ctrl_num--; + csi_irq_restore(result); +} + +csi_error_t csi_dma_ch_alloc(csi_dma_ch_t *dma_ch, int8_t ch_id, int8_t ctrl_id) +{ + CSI_PARAM_CHK(dma_ch, CSI_ERROR); + csi_error_t ret = CSI_OK; + + csi_dma_ch_desc_t ch_info = {0}; + csi_dev_t *dev_info; + dev_info = (csi_dev_t *)(dma_ch->parent); + uint32_t result = csi_irq_save(); + + if ((ctrl_id == -1) && (ch_id == -1)) { + ret = target_get_optimal_dma_channel(dma_array, inited_ctrl_num, dev_info, &ch_info); + + if (ret == CSI_OK) { + dma_array[ch_info.ctrl_idx]->alloc_status |= (uint32_t)((uint32_t)1U << (uint32_t)ch_info.ch_idx); + + dma_ch->ch_id = ch_info.ch_idx; + dma_ch->ctrl_id = ch_info.ctrl_idx; + } + } else if ((ctrl_id >= 0) && (ch_id >= 0)) { + if (dma_array[ctrl_id]->alloc_status & (uint32_t)((uint32_t)1U << (uint32_t)ch_id)) { + ret = CSI_ERROR; + } else { + dma_array[ctrl_id]->alloc_status |= (uint32_t)((uint32_t)1U << (uint32_t)ch_id); + dma_ch->ch_id = ch_id; + dma_ch->ctrl_id = ctrl_id; + + ///< TODO:清除DMA指定通道的搬运中断 + ///< TODO:清除DMA指定通道的块搬运中断 + ///< TODO:清除DMA指定通道的错误中断 + ///< TODO:清除DMA指定通道的源搬运中断 + ///< TODO:清除DMA指定通道的目的搬运中断 + + ///< TODO:配置DMA指定通道的搬运中断屏蔽 + ///< TODO:配置DMA指定通道的块搬运中断屏蔽 + ///< TODO:配置DMA指定通道的错误中断屏蔽 + + ///< TODO:关闭指定的DMA通道 + } + } else { + ret = CSI_ERROR; + } + + if (ret == CSI_ERROR) { + csi_irq_restore(result); + + } else { + slist_add(&dma_ch->next, &dma_array[dma_ch->ctrl_id]->head); + csi_irq_restore(result); + } + + dma_ch->etb_ch_id = -1; + + return ret; +} + +void csi_dma_ch_free(csi_dma_ch_t *dma_ch) +{ + CSI_PARAM_CHK_NORETVAL(dma_ch); + uint32_t result = csi_irq_save(); + + uint32_t temp_u32; + temp_u32 = 1U << (uint8_t)(dma_ch->ch_id); + + if (dma_array[dma_ch->ctrl_id]->alloc_status & temp_u32) { + dma_array[dma_ch->ctrl_id]->alloc_status &= ~((uint32_t)1 << (uint32_t)dma_ch->ch_id); + + ///< TODO:清除DMA指定通道的搬运中断 + ///< TODO:清除DMA指定通道的块搬运中断 + ///< TODO:清除DMA指定通道的错误中断 + ///< TODO:清除DMA指定通道的源搬运中断 + ///< TODO:清除DMA指定通道的目的搬运中断 + + ///< TODO:对DMA的搬运中断掩码进行允许掩码位写入的操作 + ///< TODO:对DMA的错误中断掩码进行允许掩码位写入的操作 + + ///< TODO:关闭指定的DMA通道 + + slist_del(&dma_ch->next, &dma_array[dma_ch->ctrl_id]->head); + } + + csi_irq_restore(result); +} + +csi_error_t csi_dma_ch_config(csi_dma_ch_t *dma_ch, csi_dma_ch_config_t *config) +{ + CSI_PARAM_CHK(dma_ch, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< TODO:关闭DMA指定通道的所有中断 + + /* Initializes corresponding channel registers */ + + switch (config->dst_tw) { + case DMA_DATA_WIDTH_8_BITS: + ///< TODO:配置正在使用的DMA通道的目地端传输数据的位宽为8 + break; + + case DMA_DATA_WIDTH_16_BITS: + ///< TODO:配置正在使用的DMA通道的目地端传输数据的位宽为16 + break; + + case DMA_DATA_WIDTH_32_BITS: + ///< TODO:配置正在使用的DMA通道的目地端传输数据的位宽为32 + break; + + default: + break; + } + + switch (config->src_tw) { + case DMA_DATA_WIDTH_8_BITS: + ///< TODO:配置正在使用的DMA通道的源端传输数据的位宽为8 + break; + + case DMA_DATA_WIDTH_16_BITS: + ///< TODO:配置正在使用的DMA通道的源端传输数据的位宽为16 + break; + + case DMA_DATA_WIDTH_32_BITS: + ///< TODO:配置正在使用的DMA通道的源端传输数据的位宽为32 + break; + + default: + break; + } + + switch (config->src_inc) { + case DMA_ADDR_INC : + ///< TODO:配置正在使用的DMA通道的源端的地址是增加的 + break; + + case DMA_ADDR_DEC: + ///< TODO:配置正在使用的DMA通道的源端的地址是减少的 + break; + + case DMA_ADDR_CONSTANT: + ///< TODO:配置正在使用的DMA通道的源端的地址是不变的 + break; + + default: + break; + } + + switch (config->dst_inc) { + case DMA_ADDR_INC : + ///< TODO:配置正在使用的DMA通道的目地端的地址是增加的 + break; + + case DMA_ADDR_DEC: + ///< TODO:配置正在使用的DMA通道的目地端的地址是减少的 + break; + + case DMA_ADDR_CONSTANT: + ///< TODO:配置正在使用的DMA通道的目地端的地址是不变的 + break; + + default: + break; + } + + ///< TODO:配置正在使用的DMA通道的突发传输长度 + + switch (config->trans_dir) { + case DMA_MEM2MEM: + ///< TODO:配置正在使用的DMA通道的传输方向为内存到内存 + ///< TODO:配置正在使用的DMA通道的目地端的握手方式为软件握手 + ///< TODO:配置正在使用的DMA通道的源端的握手方式为软件握手 + break; + + case DMA_MEM2PERH: + ///< TODO:配置正在使用的DMA通道的传输方向为内存到外设 + ///< TODO:配置正在使用的DMA通道的目地端的握手方式为硬件握手 + ///< TODO:配置正在使用的DMA通道的源端的握手方式为软件握手 + ///< TODO:配置正在使用的DMA通道的目地端的握手号 + break; + + case DMA_PERH2MEM: + ///< TODO:配置正在使用的DMA通道的传输方向为外设到内存 + ///< TODO:配置正在使用的DMA通道的目地端的握手方式为软件握手 + ///< TODO:配置正在使用的DMA通道的源端的握手方式为硬件握手 + ///< TODO:配置正在使用的DMA通道的源端的握手号 + break; + + default: + break; + } + + if (config->src_reload_en == 1) { + ///< TODO:配置正在使用的DMA通道的源地址自动重载 + } else { + ///< TODO:配置正在使用的DMA通道的源地址不是自动重载 + } + + if (config->dst_reload_en == 1) { + ///< TODO:配置正在使用的DMA通道的目地地址自动重载 + } else { + ///< TODO:配置正在使用的DMA通道的目地地址不是自动重载 + } + + return ret; +} + +csi_error_t csi_dma_ch_attach_callback(csi_dma_ch_t *dma_ch, void *callback, void *arg) +{ + csi_error_t ret = CSI_OK; + CSI_PARAM_CHK(dma_ch, CSI_ERROR); + + dma_ch->callback = callback; + dma_ch->arg = arg; + + ///< TODO:配置DMA0/DMA1的搬运中断、块搬运中断、错误中断屏蔽寄存器的写使能位和屏蔽位 + + ///< TODO:配置DMA0/DMA1的搬运中断、块搬运中断、源搬运中断、目地搬运中断、错误中断清除寄存器 + + return ret; +} + +void csi_dma_ch_detach_callback(csi_dma_ch_t *dma_ch) +{ + CSI_PARAM_CHK_NORETVAL(dma_ch); + + dma_ch->callback = NULL; + dma_ch->arg = NULL; + + ///< TODO:配置DMA0/DMA1的搬运中断、块搬运中断、源搬运中断、目地搬运中断、错误中断屏蔽寄存器的写使能位 + ///< TODO:配置DMA0/DMA1的搬运中断、块搬运中断、源搬运中断、目地搬运中断、错误中断清除寄存器 + + ///< TODO:关闭DMA中断 + +} + +void csi_dma_ch_start(csi_dma_ch_t *dma_ch, void *srcaddr, void *dstaddr, uint32_t length) +{ + CSI_PARAM_CHK_NORETVAL(dma_ch); + + ///< TODO:关闭正在使用的DMA通道 + + if (srcaddr != NULL) { + ///< TODO:配置正在使用的DMA通道的源地址 + } + + if (dstaddr != NULL) { + ///< TODO:配置正在使用的DMA通道的目地地址 + } + + ///< TODO:配置DMA0/DMA1的搬运中断、块搬运中断、源搬运中断、目地搬运中断、错误中断清除寄存器 + + ///< TODO:使能正在使用的DMA通道的中断 + ///< TODO:打开申请到的DMA通道 + +} + +void csi_dma_ch_stop(csi_dma_ch_t *dma_ch) +{ + int8_t ch = dma_ch->ch_id; + + if (ch >= CONFIG_DMA_CHANNEL_NUM || ch < 0) { + return; + } + + ///< TODO:关闭DMA通道 + ///< TODO:关闭DMA中断 + +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/dw_uart_ll.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/dw_uart_ll.c new file mode 100644 index 00000000000..15ae00bebdc --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/dw_uart_ll.c @@ -0,0 +1,164 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file dw_uart_ll.c + * @brief dw uart ll driver + * @version V1.0 + * @date 18. December 2024 + ******************************************************************************/ +#include + +int32_t dw_uart_wait_idle(dw_uart_regs_t *uart_base) +{ + uint32_t timecount = 0U; + int32_t ret = 0; + + while ((uart_base->USR & DW_UART_USR_BUSY_SET) && (timecount < UART_BUSY_TIMEOUT)) { + timecount++; + } + + if (timecount >= UART_BUSY_TIMEOUT) { + ret = -1; + } + + return ret; +} + +int32_t dw_uart_wait_timeout(dw_uart_regs_t *uart_base) +{ + uint32_t timecount = 0U; + int32_t ret = 0; + + while ((uart_base->LSR & 0x81U) || (uart_base->USR & 0x1U)) { + uart_base->LSR; + uart_base->RBR; + timecount++; + + if (timecount >= UART_BUSY_TIMEOUT) { + ret = -1; + break; + } + } + + if (ret == 0) { + ret = dw_uart_wait_idle(uart_base); + } + + return ret; +} + +int32_t dw_uart_config_baudrate(dw_uart_regs_t *uart_base, uint32_t baud, uint32_t uart_freq) +{ + uint32_t divisor; + int32_t ret = 0; + ret = dw_uart_wait_timeout(uart_base); + + if (ret == 0) { + if ((uart_freq / 16) % baud >= (baud / 2)) + divisor = (uart_freq / 16) / baud + 1; + else + divisor = (uart_freq / 16) / baud; + + uart_base->LCR |= DW_UART_LCR_DLAB_EN; + + /* DLL and DLH is lower 8-bits and higher 8-bits of divisor.*/ + uart_base->DLH = (divisor >> 8U) & 0xFFU; + uart_base->DLL = divisor & 0xFFU; + /* + * The DLAB must be cleared after the baudrate is setted + * to access other registers. + */ + uart_base->LCR &= (~DW_UART_LCR_DLAB_EN); + } + + return ret; +} + +int32_t dw_uart_config_stop_bits(dw_uart_regs_t *uart_base, uint32_t stop_bits) +{ + int32_t ret; + ret = dw_uart_wait_timeout(uart_base); + + if (ret == 0) { + + //when data length is 5 bits, use dw_uart_config_stop_bits_2 will be 1.5 stop bits + if (stop_bits == 1U) { + dw_uart_config_stop_bits_1(uart_base); + } else if (stop_bits == 2U) { + dw_uart_config_stop_bits_2(uart_base); + } + } + + //FIXME: no console output sometimes + mdelay(1); + + return ret; +} + +int32_t dw_uart_config_parity_none(dw_uart_regs_t *uart_base) +{ + int32_t ret; + ret = dw_uart_wait_timeout(uart_base); + + if (ret == 0) { + uart_base->LCR &= (~DW_UART_LCR_PEN_EN); + } + + return ret; +} + +int32_t dw_uart_config_parity_odd(dw_uart_regs_t *uart_base) +{ + int32_t ret; + + ret = dw_uart_wait_timeout(uart_base); + + if (ret == 0) { + uart_base->LCR |= DW_UART_LCR_PEN_EN; + uart_base->LCR &= ~(DW_UART_LCR_EPS_EN); + } + + return ret; +} + +int32_t dw_uart_config_parity_even(dw_uart_regs_t *uart_base) +{ + int32_t ret; + + ret = dw_uart_wait_timeout(uart_base); + + if (ret == 0) { + uart_base->LCR |= DW_UART_LCR_PEN_EN; + uart_base->LCR |= DW_UART_LCR_EPS_EN; + } + + return ret; +} + +int32_t dw_uart_config_data_bits(dw_uart_regs_t *uart_base, uint32_t data_bits) +{ + int32_t ret; + + ret = dw_uart_wait_timeout(uart_base); + + uart_base->LCR &= 0xFCU; + uart_base->LCR |= (data_bits - 5U); + + return ret; +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/etb.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/etb.c new file mode 100644 index 00000000000..a191b0a9277 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/etb.c @@ -0,0 +1,178 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file wj_etb.c + * @brief CSI Source File for etb Driver + * @version V1.0 + * @date 19. December 2024 + * @vendor csky + * @name wj_etb + * @ip_id 0x111000010 + * @model etb + * @tag DEV_WJ_ETB_TAG + ******************************************************************************/ +#include +#include +#include + +static uint8_t csi_etb_alloc_status[4]; + +static int32_t check_is_alloced(int32_t ch_id) +{ + uint32_t ch_offset, ch_group; + int32_t ret = 0; + uint8_t status = 0U; + + ch_group = (uint32_t)((uint32_t)ch_id / 8U); + ch_offset = (uint32_t)((uint32_t)ch_id % 8U); + + status = csi_etb_alloc_status[ch_group]; + + status &= (uint8_t)(1U << (uint8_t)ch_offset); + + if (status != 0U) { + ret = -1; + } + + return ret; +} + +static void set_ch_alloc_status(int32_t ch_id, uint32_t status) +{ + uint32_t ch_offset, ch_group; + + ch_group = (uint32_t)((uint32_t)ch_id / 8U); + ch_offset = (uint32_t)((uint32_t)ch_id % 8U); + + if (status == 1U) { + csi_etb_alloc_status[ch_group] |= (uint8_t)(1U << (uint8_t)ch_offset); + } else if (status == 0U) { + csi_etb_alloc_status[ch_group] &= ~(uint8_t)(1U << (uint8_t)ch_offset); + } +} + +csi_error_t csi_etb_init(void) +{ + ///< TODO:使能ETB + + return CSI_OK; +} + +void csi_etb_uninit(void) +{ + ///< TODO:禁止ETB +} + +int32_t csi_etb_ch_alloc(csi_etb_ch_type_t ch_type) +{ + int32_t ret, ret_ch; + uint32_t result = csi_irq_save(); + + switch (ch_type) { + case ETB_CH_MORE_TRIGGER_ONE: + ret_ch = 0; + + if (check_is_alloced(ret_ch) < 0) { + ret = CSI_ERROR; + } else { + ret = ret_ch; + } + + break; + + case ETB_CH_ONE_TRIGGER_MORE: + for (ret_ch = 1; ret_ch < 3; ret_ch++) { + if (check_is_alloced(ret_ch) != -1) { + break; + } + } + + if (ret_ch == 3) { + ret = CSI_ERROR; + } else { + ret = ret_ch; + } + + break; + + case ETB_CH_ONE_TRIGGER_ONE: + for (ret_ch = 3; ret_ch < 32; ret_ch++) { + if (check_is_alloced(ret_ch) != -1) { + break; + } + } + + if (ret_ch == 32) { + ret = CSI_ERROR; + } else { + ret = ret_ch; + } + + break; + + default: + ret = CSI_ERROR; + } + + if (ret != CSI_ERROR) { + set_ch_alloc_status(ret_ch, 1U); + } + + csi_irq_restore(result); + return ret; +} + +void csi_etb_ch_free(int32_t ch_id) +{ + uint32_t result = csi_irq_save(); + set_ch_alloc_status(ch_id, 0U); + csi_irq_restore(result); +} + +csi_error_t csi_etb_ch_config(int32_t ch_id, csi_etb_config_t *config) +{ + CSI_PARAM_CHK(config, CSI_ERROR); + csi_error_t ret = CSI_OK; + + if (config->ch_type == ETB_CH_ONE_TRIGGER_ONE) { + if (ch_id < 3) { + ret = CSI_ERROR; + } else { + ///< TODO:配置ETB的通道 + } + } else { + ret = CSI_UNSUPPORTED; + } + + if (ret == CSI_OK) { + ///< TODO:配置ETB通道的触发 + } + + return ret; +} + +void csi_etb_ch_start(int32_t ch_id) +{ + ///< TODO:使能ETB通道 +} + +void csi_etb_ch_stop(int32_t ch_id) +{ + ///< TODO:禁止ETB通道 +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/gpio.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/gpio.c new file mode 100644 index 00000000000..78afb906725 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/gpio.c @@ -0,0 +1,271 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file dw_gpio.c + * @brief + * @version + * @date 2020-01-08 + ******************************************************************************/ + +#include + +#include +#include +#include +#include + +extern csi_error_t csi_pin_mode(pin_name_t pin_name, csi_gpio_mode_t mode); + +static void dw_gpio_irqhandler(void *args) +{ + + ///< TODO:获取GPIO中断的状态 + ///< TODO:清除中断 + ///< TODO:根据中断状态执行用户回调函数 + +} + +csi_error_t csi_gpio_init(csi_gpio_t *gpio, uint32_t port_idx) +{ + CSI_PARAM_CHK(gpio, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + ///< 本函数初始化GPIO控制器,非单个GPIO PIN + + ///< 获取中断号、基地址等相关信息 + if (target_get(DEV_DW_GPIO_TAG, port_idx, &gpio->dev) != CSI_OK) { + ret = CSI_ERROR; + } + + return ret; +} + +void csi_gpio_uninit(csi_gpio_t *gpio) +{ + CSI_PARAM_CHK_NORETVAL(gpio); + + ///< TODO:重置GPIO相关寄存器 + + ///< 禁止中断控制器对应的中断和注销GPIO的中断服务函数 + csi_irq_disable((uint32_t)gpio->dev.irq_num); + csi_irq_detach((uint32_t)gpio->dev.irq_num); + + ///< 释放句柄 + memset(gpio, 0, sizeof(csi_gpio_t)); +} + +csi_error_t csi_gpio_dir(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_dir_t dir) +{ + CSI_PARAM_CHK(gpio, CSI_ERROR); + CSI_PARAM_CHK(pin_mask, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + ///< 注意:pin_mask代表正在操作的GPIO PIN,例如pin_mask = 0x3,则代表正在操作GPIO PIN_0 和GPIO PIN_1 + + ///< TODO:根据dir和pin_mask设置相应GPIO口数据传输的方向 + + return ret; +} + +csi_error_t csi_gpio_mode(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_mode_t mode) +{ + CSI_PARAM_CHK(gpio, CSI_ERROR); + CSI_PARAM_CHK(pin_mask, CSI_ERROR); + + csi_error_t ret = CSI_OK; + csi_error_t temp; + uint8_t offset = 0U; + pin_name_t pin_name; + + /* set pin mode */ + while (pin_mask) { + if (pin_mask & 0x01U) { + ///< 获取使用的GPIO口的引脚名称 + pin_name = csi_pin_get_pinname_by_gpio(gpio->dev.idx, offset); + + if ((uint8_t)pin_name != 0xFFU) { + ///< 设置GPIO的模式:GPIO_MODE_PULLNONE、GPIO_MODE_PULLUP、GPIO_MODE_PULLDOWN、GPIO_MODE_OPEN_DRAIN、GPIO_MODE_PUSH_PULL + temp = csi_pin_mode(pin_name, mode); + + if (temp == CSI_ERROR) { /* return CSI_ERROR if csi_pin_mode return CSI_ERROR */ + ret = CSI_ERROR; + break; + } else if (temp == CSI_UNSUPPORTED) { /* return CSI_UNSUPPORTED if csi_pin_mode return CSI_UNSUPPORTED */ + ret = CSI_UNSUPPORTED; + } + } + } + + pin_mask >>= 1U; + offset++; + } + + return ret; +} + +csi_error_t csi_gpio_irq_mode(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_irq_mode_t mode) +{ + CSI_PARAM_CHK(gpio, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + switch (mode) { + /* rising edge interrupt mode */ + case GPIO_IRQ_MODE_RISING_EDGE: + ///< TODO:根据pin_mask和mode设置中断类型和中断极性 + break; + + /* falling edge interrupt mode */ + case GPIO_IRQ_MODE_FALLING_EDGE: + ///< TODO:根据pin_mask和mode设置中断类型和中断极性 + break; + + /* low level interrupt mode */ + case GPIO_IRQ_MODE_LOW_LEVEL: + ///< TODO:根据pin_mask和mode设置中断类型和中断极性 + break; + + /* high level interrupt mode */ + case GPIO_IRQ_MODE_HIGH_LEVEL: + ///< TODO:根据pin_mask和mode设置中断类型和中断极性 + break; + + /* double edge interrupt mode */ + case GPIO_IRQ_MODE_BOTH_EDGE: + default: + ret = CSI_UNSUPPORTED; + break; + } + + return ret; +} + +csi_error_t csi_gpio_irq_enable(csi_gpio_t *gpio, uint32_t pin_mask, bool enable) +{ + CSI_PARAM_CHK(gpio, CSI_ERROR); + CSI_PARAM_CHK(pin_mask, CSI_ERROR); + + ///< TODO:打开或者关闭GPIO + + return CSI_OK; +} + +csi_error_t csi_gpio_debonce(csi_gpio_t *gpio, uint32_t pin_mask, bool enable) +{ + CSI_PARAM_CHK(gpio, CSI_ERROR); + CSI_PARAM_CHK(pin_mask, CSI_ERROR); + + return CSI_UNSUPPORTED; +} + +void csi_gpio_toggle(csi_gpio_t *gpio, uint32_t pin_mask) +{ + CSI_PARAM_CHK_NORETVAL(gpio); + CSI_PARAM_CHK_NORETVAL(pin_mask); + + ///< TODO:翻转GPIO口输出状态,例如,当前GPIO的输出状态是高电平,翻转之后则为低电平 +} + +void csi_gpio_write(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_pin_state_t value) +{ + CSI_PARAM_CHK_NORETVAL(gpio); + CSI_PARAM_CHK_NORETVAL(pin_mask); + + ///< TODO:根据value写数据寄存器 + +} + +uint32_t csi_gpio_read(csi_gpio_t *gpio, uint32_t pin_mask) +{ + CSI_PARAM_CHK(gpio, CSI_ERROR); + CSI_PARAM_CHK(pin_mask, CSI_ERROR); + uint32_t status = 0U; + + ///< TODO:读取相应引脚的信号输入状态 + + return status; + +} + +csi_error_t csi_gpio_attach_callback(csi_gpio_t *gpio, void *callback, void *arg) +{ + CSI_PARAM_CHK(gpio, CSI_ERROR); + CSI_PARAM_CHK(callback, CSI_ERROR); + + ///< TODO:清除中断 + + gpio->callback = callback; + gpio->arg = arg; + + ///< 注册GPIO的中断服务函数,使能中断控制器对应的中断 + csi_irq_attach((uint32_t)gpio->dev.irq_num, &dw_gpio_irqhandler, &gpio->dev); + csi_irq_enable((uint32_t)gpio->dev.irq_num); + + return CSI_OK; +} + +void csi_gpio_detach_callback(csi_gpio_t *gpio) +{ + CSI_PARAM_CHK_NORETVAL(gpio); + + gpio->callback = NULL; + gpio->arg = NULL; + + ///< 注销GPIO的中断服务函数,禁止中断控制器对应的中断 + csi_irq_disable((uint32_t)gpio->dev.irq_num); + csi_irq_detach((uint32_t)gpio->dev.irq_num); +} + +#ifdef CONFIG_PM +csi_error_t dw_gpio_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action) +{ + CSI_PARAM_CHK(dev, CSI_ERROR); + + csi_error_t ret = CSI_OK; + csi_pm_dev_t *pm_dev = &dev->pm_dev; + + switch (action) { + case PM_DEV_SUSPEND: + ///< TODO:恢复GPIO寄存器 + break; + + case PM_DEV_RESUME: + ///< TODO:保存GPIO寄存器 + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +csi_error_t csi_gpio_enable_pm(csi_gpio_t *gpio) +{ + ///< TODO:注册GPIO低功耗处理函数dw_gpio_pm_action +} + +void csi_gpio_disable_pm(csi_gpio_t *gpio) +{ + csi_pm_dev_unregister(&gpio->dev); +} +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/gpio_pin.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/gpio_pin.c new file mode 100644 index 00000000000..d76a16e5b75 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/gpio_pin.c @@ -0,0 +1,215 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file gpio_pin.c + * @brief + * @version + * @date 2020-06-28 + ******************************************************************************/ +#include + +#include +#include +#include +#include +#include + +///< TODO:CONFIG_GPIO_NUM需要根据实际情况进行设置 +#define CONFIG_GPIO_NUM 2U ///< 配置的GPIO的数量GPIOA,GPIOB + +typedef struct { + csi_gpio_t gpio; + csi_gpio_pin_t *pin[32]; +} csi_gpio_manage_t; + +csi_gpio_manage_t g_gpio_manage[CONFIG_GPIO_NUM]; + +extern csi_error_t csi_pin_mode(pin_name_t pin_name, csi_gpio_mode_t mode); +extern csi_error_t csi_gpio_debonce(csi_gpio_t *gpio, uint32_t pin_mask, bool enable); + +static void gpio_manage_callback(csi_gpio_t *gpio, uint32_t pins, void *arg) +{ + csi_gpio_pin_t **pin; + uint8_t pin_idx = 0U; + + do { + if (pins == 0U) { + break ; + } + + pin = &g_gpio_manage[gpio->dev.idx].pin[0]; + + do { + while (!(pins & 0x1U)) { + pins >>= 1U; + pin_idx++; + } + + if (pin[pin_idx] && pin[pin_idx]->callback) { + pin[pin_idx]->callback(pin[pin_idx], pin[pin_idx]->arg); + } + + pins >>= 1U; + pin_idx++; + } while (pins); + } while(0); +} + +csi_error_t csi_gpio_pin_init(csi_gpio_pin_t *pin, pin_name_t pin_name) +{ + CSI_PARAM_CHK(pin, CSI_ERROR); + + csi_error_t ret = CSI_OK; + size_t state; + uint32_t idx; + + ///< 获取GPIO口的引脚名称 + idx = csi_pin_get_gpio_channel(pin_name); + + if (idx == 0xFFFFFFFFU) { + ret = CSI_ERROR; + } else { + pin->pin_idx = idx; + } + + idx = csi_pin_get_gpio_devidx(pin_name); + + if (idx == 0xFFFFFFFFU) { + ret = CSI_ERROR; + } else { + state = csi_irq_save(); + + if (!g_gpio_manage[idx].gpio.dev.reg_base) { + csi_gpio_init(&g_gpio_manage[idx].gpio, idx); + csi_gpio_attach_callback(&g_gpio_manage[idx].gpio, gpio_manage_callback, NULL); + } + + csi_irq_restore(state); + pin->gpio = &g_gpio_manage[idx].gpio; + g_gpio_manage[idx].pin[pin->pin_idx] = pin; + } + + return ret; +} + +void csi_gpio_pin_uninit(csi_gpio_pin_t *pin) +{ + CSI_PARAM_CHK_NORETVAL(pin); + + size_t state; + + for (uint8_t i = 0U; i < CONFIG_GPIO_NUM; i++) { + state = csi_irq_save(); + + if (&g_gpio_manage[i].gpio == pin->gpio) { + g_gpio_manage[i].pin[pin->pin_idx] = NULL; + } + + csi_irq_restore(state); + } + + pin->pin_idx = 0U; + pin->callback = NULL; + pin->arg = NULL; +} + +csi_error_t csi_gpio_pin_attach_callback(csi_gpio_pin_t *pin, void *callback, void *arg) +{ + CSI_PARAM_CHK(pin, CSI_ERROR); + CSI_PARAM_CHK(callback, CSI_ERROR); + + ///< TODO:获取中断状态 + + ///< TODO:根据中断状态清除GPIO的中断 + + pin->callback = callback; + pin->arg = arg; + + return CSI_OK; +} + +csi_error_t csi_gpio_pin_dir(csi_gpio_pin_t *pin, csi_gpio_dir_t dir) +{ + CSI_PARAM_CHK(pin, CSI_ERROR); + + ///< 设置GPIO口数据的传输方向 + return csi_gpio_dir(pin->gpio, (uint32_t)1U << pin->pin_idx, dir); +} + +csi_error_t csi_gpio_pin_mode(csi_gpio_pin_t *pin, csi_gpio_mode_t mode) +{ + CSI_PARAM_CHK(pin, CSI_ERROR); + + ///< 设置GPIO口的模式 + return csi_gpio_mode(pin->gpio, (uint32_t)1U << pin->pin_idx, mode); +} + +csi_error_t csi_gpio_pin_irq_mode(csi_gpio_pin_t *pin, csi_gpio_irq_mode_t mode) +{ + CSI_PARAM_CHK(pin, CSI_ERROR); + + ///< 设置GPIO中断的模式 + return csi_gpio_irq_mode(pin->gpio, (uint32_t)1U << pin->pin_idx, mode); +} + +csi_error_t csi_gpio_pin_irq_enable(csi_gpio_pin_t *pin, bool enable) +{ + CSI_PARAM_CHK(pin, CSI_ERROR); + + ///< 使能GPIO口的中断 + return csi_gpio_irq_enable(pin->gpio, (uint32_t)1U << pin->pin_idx, enable); +} + +csi_error_t csi_gpio_pin_debounce(csi_gpio_pin_t *pin, bool enable) +{ + CSI_PARAM_CHK(pin, CSI_ERROR); + + return csi_gpio_debonce(pin->gpio, (uint32_t)1U << pin->pin_idx, enable); +} + +void csi_gpio_pin_write(csi_gpio_pin_t *pin, csi_gpio_pin_state_t value) +{ + CSI_PARAM_CHK_NORETVAL(pin); + + ///< 用value写GPIO口的信号 + return csi_gpio_write(pin->gpio, (uint32_t)1U << pin->pin_idx, value); +} + +void csi_gpio_pin_toggle(csi_gpio_pin_t *pin) +{ + CSI_PARAM_CHK_NORETVAL(pin); + + ///< 翻转GPIO口的电平 + return csi_gpio_toggle(pin->gpio, (uint32_t)1U << pin->pin_idx); +} + +csi_gpio_pin_state_t csi_gpio_pin_read(csi_gpio_pin_t *pin) +{ + csi_gpio_pin_state_t state; + + ///< 读取GPIO口信号的状态 + if (csi_gpio_read(pin->gpio, (uint32_t)1U << pin->pin_idx) != 0U) { + state = GPIO_PIN_HIGH; + } else { + state = GPIO_PIN_LOW; + } + + return state; +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/i2s.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/i2s.c new file mode 100644 index 00000000000..e18e16d4a2c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/i2s.c @@ -0,0 +1,888 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include + +extern uint16_t i2s_tx_hs_num[]; +extern uint16_t i2s_rx_hs_num[]; + +void wj_i2s_dma_event_cb(csi_dma_ch_t *dma, csi_dma_event_t event, void *arg) +{ + CSI_PARAM_CHK_NORETVAL(dma); + + csi_i2s_t *i2s = (csi_i2s_t *)dma->parent; + + if (event == DMA_EVENT_TRANSFER_ERROR) {/* DMA transfer ERROR */ + if (i2s->tx_dma->ch_id == dma->ch_id) { + /* to do tx error action */ + i2s->state.error = 1U; + + if (i2s->callback) { + i2s->callback(i2s, I2S_EVENT_ERROR, i2s->arg); + } + } else if (i2s->rx_dma->ch_id == dma->ch_id) { + /* to do rx error action */ + i2s->state.error = 1U; + + if (i2s->callback) { + i2s->callback(i2s, I2S_EVENT_ERROR, i2s->arg); + } + } + + } else if (event == DMA_EVENT_TRANSFER_DONE) {/* DMA transfer complete */ + if ((i2s->tx_dma != NULL) && (i2s->tx_dma->ch_id == dma->ch_id)) { + /* to do tx action */ + uint32_t read_len = i2s->tx_period; + i2s->tx_buf->read = (i2s->tx_buf->read + read_len) % i2s->tx_buf->size; + + if (i2s->tx_buf->data_len == 0U) { + i2s->tx_buf->data_len = 0U; + + if (i2s->callback) { + i2s->callback(i2s, I2S_EVENT_TX_BUFFER_EMPTY, i2s->arg); + } + + } else { + i2s->tx_buf->data_len -= read_len; + } + + ///< TODO:调用csi_dma_ch_start开始DMA发送数据 + + if (i2s->callback) { + i2s->callback(i2s, I2S_EVENT_SEND_COMPLETE, i2s->arg); + } + } else { + + soc_dcache_clean_invalid_range((unsigned long)(i2s->rx_buf->buffer + i2s->rx_buf->write), i2s->rx_period); + + ///< TODO:调用csi_dma_ch_start开启DMA接收数据 + + if (i2s->callback && i2s->rx_buf->data_len != 0) { + i2s->callback(i2s, I2S_EVENT_RECEIVE_COMPLETE, i2s->arg); + } else { + i2s->callback(i2s, I2S_EVENT_RX_BUFFER_FULL, i2s->arg); + } + } + } +} + +/** + \brief I2S init + \param[in] i2s i2s handle to operate. + \param[in] idx i2s interface idx + \return error code +*/ +csi_error_t csi_i2s_init(csi_i2s_t *i2s, uint32_t idx) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< 获取中断号、基地址等相关信息 + ret = target_get(DEV_WJ_I2S_TAG, idx, &i2s->dev); + + if (ret == CSI_OK) { + ///< TODO:清除I2S的中断 + } + + i2s->rx_dma = NULL; + i2s->tx_dma = NULL; + i2s->rx_buf = NULL; + i2s->tx_buf = NULL; + i2s->state.error = 0U; + i2s->state.readable = 0U; + i2s->state.writeable = 0U; + i2s->priv = (void *)0U; + i2s->callback = NULL; + return ret; +} + +/** + \brief I2S uninit + \param[in] i2s i2s handle to operate. + \return none +*/ +void csi_i2s_uninit(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK_NORETVAL(i2s); + i2s->rx_dma = NULL; + i2s->tx_dma = NULL; + i2s->rx_buf = NULL; + i2s->tx_buf = NULL; + i2s->state.error = 0U; + i2s->state.readable = 0U; + i2s->state.writeable = 0U; + + ///< TODO:关闭I2S的使能 + ///< TODO:清除I2S的中断 + +} + +/** + \brief I2S enable + \param[in] i2s i2s handle to operate. + \param[in] en 1 enable, 0 disable + \return none +*/ +void csi_i2s_enable(csi_i2s_t *i2s, bool enable) +{ + CSI_PARAM_CHK_NORETVAL(i2s); + + if (enable) { + ///< TODO:使能I2S + } else { + ///< TODO:不使能I2S + } +} + +/** + \brief I2S config + \param[in] i2s i2s handle to operate. + \param[in] config i2s config param + \return error code +*/ +csi_error_t csi_i2s_format(csi_i2s_t *i2s, csi_i2s_format_t *format) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + CSI_PARAM_CHK(format, CSI_ERROR); + csi_error_t ret = CSI_OK; + + switch (format->mode) { + case I2S_MODE_MASTER: + ///< TODO:设置I2S为主机接收模式 + ///< TODO:设置I2S为主机发送模式 + break; + + case I2S_MODE_SLAVE: + ///< TODO:设置I2S为从机接收模式 + ///< TODO:设置I2S为从机发送模式 + break; + + default: + ret = CSI_ERROR; + break; + } + + switch (format->protocol) { + case I2S_PROTOCOL_I2S: + ///< TODO:设置I2S的接收为I2S格式 + ///< TODO:设置I2S的发送为I2S格式 + break; + + case I2S_PROTOCOL_MSB_JUSTIFIED: + ///< TODO:设置I2S的接收为left-justified格式 + ///< TODO:设置I2S的发送为left-justified格式 + break; + + case I2S_PROTOCOL_LSB_JUSTIFIED: + ///< TODO:设置I2S的接收为right-justified格式 + ///< TODO:设置I2S的发送为right-justified格式 + break; + + case I2S_PROTOCOL_PCM: + ///< TODO:设置I2S的接收为PCM格式 + ///< TODO:设置I2S的发送为PCM格式 + break; + + default: + ret = CSI_ERROR; + break; + } + + switch (format->width) { + case I2S_SAMPLE_WIDTH_16BIT: + ///< TODO:设置I2S的数据宽度为16位 + break; + + case I2S_SAMPLE_WIDTH_24BIT: + ///< TODO:设置I2S的数据宽度为24位 + break; + + case I2S_SAMPLE_WIDTH_32BIT: + ///< TODO:设置I2S的数据宽度为32位 + break; + + default: + ret = CSI_UNSUPPORTED; + break; + } + + if (format->mode == I2S_MODE_MASTER) { + + ///< TODO:设置I2S获取wsclk对应的分频寄存器 + ///< TODO:设置I2S获取reference clock对应的分频寄存器为0 + + } else { + ///< TODO:设置从机接收模式音频输入速率由硬件自动检测 + } + + if (format->polarity) { + ///< TODO:配置发送模式高电平对应的时左声道的数据 + ///< TODO:配置接收模式高电平对应的时左声道的数据 + } else { + ///< TODO:配置发送模式高电平对应的时右声道的数据 + ///< TODO:配置接收模式高电平对应的时右声道的数据 + } + + switch (format->sclk_nfs) { + case I2S_SCLK_16FS: + ///< TODO:配置接收模式sclk的频率为16*FS + break; + + case I2S_SCLK_32FS: + ///< TODO:配置接收模式sclk的频率为32*FS + break; + + case I2S_SCLK_48FS: + ///< TODO:配置接收模式sclk的频率为48*FS + format->mclk_nfs = I2S_MCLK_384FS; ///< if SCLK_SEL=01 then mclk_o=384*fs,select MCLK_SEL:384fs + break; + + case I2S_SCLK_64FS: + ///< TODO:配置接收模式sclk的频率为64*FS + break; + + default: + break; + } + + if (format->mclk_nfs == I2S_MCLK_384FS) { + ///< TODO:配置接收模式mclk的频率为384*FS + } else { + ///< TODO:配置接收模式mclk的频率为256*FS + } + + return ret; +} + +/** + \brief Set the i2s tx mono + \param[in] i2s i2s handle to operate. + \param[in] Mono channel selection. + \param[in] bool mono mode enable + \return error code +*/ +csi_error_t csi_i2s_tx_select_sound_channel(csi_i2s_t *i2s, csi_i2s_sound_channel_t ch) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + + switch (ch) { + case I2S_LEFT_CHANNEL: + ///< TODO:配置发送数据模式数据源是单声道数据(左右声道数据相同) + ///< TODO:配置发送模式低电平对应的数据是左声道的数据 + break; + + case I2S_RIGHT_CHANNEL: + ///< TODO:配置发送数据模式数据源是单通道数据(左右声道数据相同) + ///< TODO:配置发送模式高电平对应的数据是左声道的数据 + break; + + case I2S_LEFT_RIGHT_CHANNEL: + ///< TODO:配置发送数据模式数据源是双声道数据 + break; + + default: + break; + } + + return ret; +} + +/** + \brief Set the i2s rx mono + \param[in] i2s i2s handle to operate. + \param[in] Mono channel selection. + \param[in] bool mono mode enable + \return error code +*/ +csi_error_t csi_i2s_rx_select_sound_channel(csi_i2s_t *i2s, csi_i2s_sound_channel_t ch) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + + switch (ch) { + case I2S_LEFT_CHANNEL: + ///< TODO:配置接收数据模式数据源是单声道数据(左右声道数据相同) + ///< TODO:配置接收模式接收的的数据是左声道的数据 + break; + + case I2S_RIGHT_CHANNEL: + ///< TODO:配置接收数据模式数据源是单声道数据(左右声道数据相同) + ///< TODO:配置接收模式接收的的数据是右声道的数据 + break; + + case I2S_LEFT_RIGHT_CHANNEL: + ///< TODO:配置接收数据模式数据源是双声道数据 + break; + + default: + break; + } + + return ret; +} + +/** + \brief link DMA channel to i2s device + \param[in] i2s i2s handle to operate. + \param[in] rx_dma the DMA channel for receive, when it is NULL means to unused dma. + \return error code +*/ +csi_error_t csi_i2s_rx_link_dma(csi_i2s_t *i2s, csi_dma_ch_t *rx_dma) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + + if (rx_dma != NULL) { + rx_dma->parent = i2s; + /// 申请DMA通道 + ret = csi_dma_ch_alloc(rx_dma, -1, -1); + + if (ret == CSI_OK) { + /// 注册DMA传输完成回调函数 + csi_dma_ch_attach_callback(rx_dma, wj_i2s_dma_event_cb, NULL); + i2s->rx_dma = rx_dma; + } else { + rx_dma->parent = NULL; + ret = CSI_ERROR; + } + } else { + if (i2s->rx_dma) { + /// 注销DMA传输完成回调函数 + csi_dma_ch_detach_callback(i2s->rx_dma); + /// 释放DMA通道 + csi_dma_ch_free(i2s->rx_dma); + i2s->rx_dma = NULL; + } else { + ret = CSI_ERROR; + } + } + + return ret; +} + +/** + \brief link DMA channel to i2s device + \param[in] i2s i2s handle to operate. + \param[in] rx_dma the DMA channel for receive, when it is NULL means to unused dma. + \return error code +*/ +csi_error_t csi_i2s_tx_link_dma(csi_i2s_t *i2s, csi_dma_ch_t *tx_dma) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + + if (tx_dma != NULL) { + tx_dma->parent = i2s; + /// 申请DMA通道 + ret = csi_dma_ch_alloc(tx_dma, -1, -1); + + if (ret == CSI_OK) { + /// 注册DMA传输完成回调函数 + csi_dma_ch_attach_callback(tx_dma, wj_i2s_dma_event_cb, NULL); + i2s->tx_dma = tx_dma; + } else { + tx_dma->parent = NULL; + ret = CSI_ERROR; + } + } else { + if (i2s->tx_dma) { + /// 注销DMA传输完成回调函数 + csi_dma_ch_detach_callback(i2s->tx_dma); + /// 释放DMA通道 + csi_dma_ch_free(i2s->tx_dma); + i2s->tx_dma = NULL; + } else { + ret = CSI_ERROR; + } + } + + return ret; +} + +/** + \brief I2S rx cache config + \param[in] i2s i2s handle to operate. + \param[in] buffer i2s rx cache + \return none +*/ +void csi_i2s_rx_set_buffer(csi_i2s_t *i2s, csi_ringbuf_t *buffer) +{ + CSI_PARAM_CHK_NORETVAL(i2s); + CSI_PARAM_CHK_NORETVAL(buffer); + i2s->rx_buf = buffer; +} + +/** + \brief I2S tx cache config + \param[in] i2s i2s handle to operate. + \param[in] buffer i2s tx cache + \return none +*/ +void csi_i2s_tx_set_buffer(csi_i2s_t *i2s, csi_ringbuf_t *buffer) +{ + CSI_PARAM_CHK_NORETVAL(i2s); + CSI_PARAM_CHK_NORETVAL(buffer); + i2s->tx_buf = buffer; +} + +/** + \brief I2S rx set period.The value of period is to report a receive completion event + \ after each period value data is received. + \param[in] i2s i2s handle to operate. + \param[in] buffer i2s rx cache + \return none +*/ +csi_error_t csi_i2s_rx_set_period(csi_i2s_t *i2s, uint32_t period) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + + if (period == 0U) { + ret = CSI_ERROR; + } else { + if ((i2s->rx_buf->size % period) != 0U) { + ret = CSI_ERROR; + } else { + i2s->rx_period = period; + } + } + + return ret; +} + +/** + \brief I2S tx set period.The value of period is to report a receive completion event + \ after each period value data is send. + \param[in] i2s i2s handle to operate. + \param[in] buffer i2s tx cache + \return none +*/ +csi_error_t csi_i2s_tx_set_period(csi_i2s_t *i2s, uint32_t period) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + + if (period == 0U) { + ret = CSI_ERROR; + } else { + if ((i2s->tx_buf->size % period) != 0U) { + ret = CSI_ERROR; + } else { + i2s->tx_period = period; + } + } + + return ret; +} + +/** + \brief Get rx csi_ringbuf cache free space + \param[in] i2s i2s handle to operate. + \return buffer free space (bytes) +*/ +uint32_t csi_i2s_rx_buffer_avail(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK(i2s, 0U); + return csi_ringbuf_avail(i2s->rx_buf); +} + +/** + \brief Reset the rx csi_ringbuf, discard all data in the cache + \param[in] i2s i2s handle to operate. + \return error code +*/ +csi_error_t csi_i2s_rx_buffer_reset(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_ERROR; + csi_ringbuf_reset(i2s->rx_buf); + + if (i2s->rx_buf->buffer != NULL) { + memset(i2s->rx_buf->buffer, 0, i2s->rx_buf->size); + } + + if ((i2s->rx_buf->read == 0U) && (i2s->rx_buf->write == 0U)) { + ret = CSI_OK; + } + + return ret; +} + +/** + \brief Get tx csi_ringbuf cache free space + \param[in] i2s i2s handle to operate. + \return buffer free space (bytes) +*/ +uint32_t csi_i2s_tx_buffer_avail(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK(i2s, 0U); + return csi_ringbuf_avail(i2s->tx_buf); +} + +/** + \brief Reset the tx csi_ringbuf, discard all data in the cache + \param[in] i2s i2s handle to operate. + \return error code +*/ +csi_error_t csi_i2s_tx_buffer_reset(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_ERROR; + csi_ringbuf_reset(i2s->tx_buf); + + if (i2s->tx_buf->buffer != NULL) { + memset(i2s->tx_buf->buffer, 0, i2s->tx_buf->size); + } + + if ((i2s->tx_buf->read == 0U) && (i2s->tx_buf->write == 0U)) { + ret = CSI_OK; + } + + return ret; +} +/** + \brief Receive an amount of data to cache in blocking mode. + \param[in] i2s operate handle. + \param[in] data save receive data. + \param[in] size receive data size. + \param[in] timeout is the number of queries, not time + \return The size of data receive successfully +*/ +int32_t csi_i2s_receive(csi_i2s_t *i2s, void *data, uint32_t size) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + uint8_t *read_data = (void *)data; + int32_t read_size = 0; + + if (i2s->rx_dma == NULL) { + ///< TODO:关闭i2s + ///< TODO:设置i2s为接收模式 + ///< TODO:打开i2s + ///< TODO:循环读数据寄存器接收数据直到接收到指定长度的数据,并把接收到的数据长度存放到read_size + } else { + + while (1) { + read_size += (int32_t)csi_ringbuf_out(i2s->rx_buf, (void *)(read_data + (uint32_t)read_size), (size - (uint32_t)read_size)); + + if ((size - (uint32_t)read_size) <= 0U) { + break; + } + } + + } + + return read_size; +} + +/** + \brief Write data to the cache. + \With asynchronous sending, + \the data is first written to the cache and then output through the I2S interface. + \This function does not block, and the return value is the number + \of data that was successfully written to the cache. + \param[in] i2s operate handle. + \param[in] data send data. + \param[in] size receive data size. + \return The data size that write to cache +*/ +uint32_t csi_i2s_send_async(csi_i2s_t *i2s, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(i2s, 0U); + CSI_PARAM_CHK(data, 0U); + uint32_t write_len; + write_len = csi_ringbuf_in(i2s->tx_buf, data, size); + + if ((uint8_t *)i2s->priv) { ///< if dma is stop, then start it + soc_dcache_clean_invalid_range((unsigned long)(i2s->tx_buf->buffer + i2s->tx_buf->read), i2s->tx_period); + ///< TODO:调用csi_dma_ch_start开启DMA通道发送数据 + i2s->priv = (void *)0U; + } + + return write_len; +} + +/** + \brief Transmits an amount of data to cache in blocking mode. + \param[in] i2s operate handle. + \param[in] data send data. + \param[in] size receive data size. + \param[in] timeout is the number of queries, not time + \return The num of data witch is send successful +*/ +int32_t csi_i2s_send(csi_i2s_t *i2s, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + int32_t write_size = 0; + uint8_t *send_data = (void *)data; + + if (i2s->tx_dma == NULL) { + + ///< TODO:清除中断 + ///< TODO:关闭i2s + ///< TODO:设置i2s为发送模式 + ///< TODO:打开i2s + ///< TODO:写数据寄存器发送数据,并把发送数据的大小写到write_size + + } else { + while (1) { + write_size += (int32_t)csi_ringbuf_in(i2s->tx_buf, (void *)(send_data + (uint32_t)write_size), (size - (uint32_t)write_size)); + + if ((uint8_t *)i2s->priv) { ///< if dma is stop, then start it + soc_dcache_clean_invalid_range((unsigned long)(i2s->tx_buf->buffer + i2s->tx_buf->read), i2s->tx_period); + + ///< TODO:调用csi_dma_ch_start开启DMA通道发送数据 + i2s->priv = (void *)0U; + } + + if ((size - (uint32_t)write_size) <= 0U) { + break; + } + } + + while (!csi_ringbuf_is_empty(i2s->tx_buf)); + } + + return write_size; +} + +/** + \brief Read data from the cache. + \Using asynchronous receive, i2s writes the received data to the cache. + \This function reads data from the cache, returns the number of successful reads, + \and returns 0 if there is no data in the cache. + \param[in] i2s operate handle. + \param[in] data the buf save receive data. + \param[in] size receive data size. + \return The size of data read successfully +*/ +uint32_t csi_i2s_receive_async(csi_i2s_t *i2s, void *data, uint32_t size) +{ + CSI_PARAM_CHK(i2s, 0U); + CSI_PARAM_CHK(data, 0U); + uint32_t read_len; + read_len = csi_ringbuf_out(i2s->rx_buf, (void *)data, size); + return read_len; +} + +/** + \brief start i2s pause asynchronous send + \param[in] i2s operate handle. + \return error code +*/ +csi_error_t csi_i2s_send_pause(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + ///< TODO:关闭DMA通道 + i2s->state.writeable = 0U; + return ret; +} + +/** + \brief start i2s resume asynchronous send + \param[in] i2s operate handle. + \return error code +*/ +csi_error_t csi_i2s_send_resume(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + + soc_dcache_clean_invalid_range((unsigned long)(i2s->tx_buf->buffer + i2s->tx_buf->read), i2s->tx_period); + ///< TODO:调用csi_dma_ch_start开启DMA通道发送数据 + + i2s->state.writeable = 1U; + return ret; +} + +/** + \brief start i2s asynchronous send + \param[in] i2s operate handle. + \return error code +*/ +csi_error_t csi_i2s_send_start(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + csi_dma_ch_config_t config; + memset(&config, 0, sizeof(csi_dma_ch_config_t)); + csi_dma_ch_t *dma_ch = (csi_dma_ch_t *)i2s->tx_dma; + + ///< TODO:清除i2s中断 + ///< TODO:关闭i2s + ///< TODO:设置i2s为发送模式 + ///< TODO:使能i2s发送DMA + ///< TODO:设置DMA的触发级别为64 + + + config.src_inc = DMA_ADDR_INC; + config.dst_inc = DMA_ADDR_CONSTANT; + config.src_tw = DMA_DATA_WIDTH_32_BITS; + config.dst_tw = DMA_DATA_WIDTH_32_BITS; + config.trans_dir = DMA_MEM2PERH; + config.half_int_en = 0U; + config.handshake = i2s_tx_hs_num[i2s->dev.idx]; + + ///< TODO:使能打开i2s + memset(i2s->tx_buf->buffer, 0, i2s->tx_buf->size); + ///< 配置DMA通道 + ret = csi_dma_ch_config(dma_ch, &config); + soc_dcache_clean_invalid_range((unsigned long)(i2s->tx_buf->buffer + i2s->tx_buf->read), i2s->tx_period); + ///< TODO:调用csi_dma_ch_start开启DMA通道,开始传输数据 + ///< TODO:清FIFO + i2s->state.writeable = 1U; + + return ret; +} + +/** + \brief start i2s asynchronous receive + \param[in] i2s operate handle. + \return error code +*/ +csi_error_t csi_i2s_receive_start(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + csi_dma_ch_config_t config; + memset(&config, 0, sizeof(csi_dma_ch_config_t)); + csi_dma_ch_t *dma_ch = (csi_dma_ch_t *)i2s->rx_dma; + + ///< TODO:关闭i2s + ///< TODO:设置i2s为接收模式 + ///< TODO:使能i2s接收DMA + ///< TODO:设置DMA的触发级别 + + config.src_inc = DMA_ADDR_CONSTANT; + config.dst_inc = DMA_ADDR_INC; + config.src_tw = DMA_DATA_WIDTH_32_BITS; + config.dst_tw = DMA_DATA_WIDTH_32_BITS; + config.trans_dir = DMA_PERH2MEM; + config.half_int_en = 0U; + config.handshake = i2s_rx_hs_num[i2s->dev.idx]; + + ///< TODO:使能打开i2s + + memset(i2s->rx_buf->buffer, 0, i2s->rx_buf->size); + ///< 配置DMA通道 + ret = csi_dma_ch_config(dma_ch, &config); + + ///< TODO:获取接收FIFO中有多少数据 + ///< TODO:根据接收FIFO中的数据量读数据寄存器,清空接收FIFO + + soc_dcache_clean_invalid_range((unsigned long)(i2s->rx_buf->buffer + i2s->rx_buf->write), i2s->rx_period); + ///< TODO:调用csi_dma_ch_start开启DMA通道,开始传输数据 + i2s->state.readable = 1U; + return ret; +} + +/** + \brief stop i2s asynchronous send + \param[in] i2s operate handle. +*/ +void csi_i2s_send_stop(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK_NORETVAL(i2s); + + ///< 关闭DMA通道 + csi_dma_ch_stop(i2s->tx_dma); + csi_ringbuf_reset(i2s->tx_buf); + memset(i2s->tx_buf->buffer, 0, i2s->tx_buf->size); + + ///< TODO:等待发送FIFO为空 + + ///< TODO:清FIFO + i2s->state.writeable = 0U; +} + +/** + \brief stop i2s asynchronous receive + \param[in] i2s operate handle. + \return error code +*/ +void csi_i2s_receive_stop(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK_NORETVAL(i2s); + ///< 关闭DMA通道 + csi_dma_ch_stop(i2s->rx_dma); + csi_ringbuf_reset(i2s->rx_buf); + memset(i2s->rx_buf->buffer, 0, i2s->rx_buf->size); + ///< TODO :清FIFO + i2s->state.readable = 0U; +} + +/** + \brief attach the callback handler to i2s + \param[in] i2s operate handle. + \param[in] cb callback function + \param[in] arg user can define it by himself as callback's param + \return error code +*/ +csi_error_t csi_i2s_attach_callback(csi_i2s_t *i2s, void *callback, void *arg) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + csi_error_t ret = CSI_OK; + i2s->callback = callback; + i2s->arg = arg; + return ret; +} + +/** + \brief detach the callback handler + \param[in] i2s operate handle. + \return none +*/ +void csi_i2s_detach_callback(csi_i2s_t *i2s) +{ + CSI_PARAM_CHK_NORETVAL(i2s); + i2s->callback = NULL; + i2s->arg = NULL; +} + +/** + \brief Get i2s status. + \param[in] i2s i2s handle to operate. + \param[out] state i2s state. + \return i2s error code +*/ +csi_error_t csi_i2s_get_state(csi_i2s_t *i2s, csi_state_t *state) +{ + CSI_PARAM_CHK(i2s, CSI_ERROR); + CSI_PARAM_CHK(state, CSI_ERROR); + *state = i2s->state; + return CSI_OK; +} + +#ifdef CONFIG_PM +csi_error_t csi_i2s_enable_pm(csi_i2s_t *i2s) +{ + return CSI_UNSUPPORTED; +} + +void csi_i2s_disable_pm(csi_i2s_t *i2s) +{ + +} +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/iic.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/iic.c new file mode 100644 index 00000000000..ca9b33944b2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/iic.c @@ -0,0 +1,1180 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include + +extern uint16_t iic_tx_hs_num[]; +extern uint16_t iic_rx_hs_num[]; + +///< TODO:IIC_EEPROM_MAX_WRITE_LEN需要根据实际情况进行设置 +#define IIC_EEPROM_MAX_WRITE_LEN 0x1U ///< IIC的eeprom的最大可写长度 +///< TODO:IIC_MAX_FIFO需要根据实际情况进行设置 +#define IIC_MAX_FIFO 0x8U ///< IIC的FIFO的最大深度 + +void dw_iic_slave_tx_handler(void *arg) +{ + CSI_PARAM_CHK_NORETVAL(arg); + + ///< TODO:清除中断并获取中断状态 + + ///< TODO:根据中断状态发送数据 + ///< TODO:根据中断状态处理异常并执行用户回调函数 + +} + +void dw_iic_tx_handler(void *arg) +{ + CSI_PARAM_CHK_NORETVAL(arg); + + ///< TODO:清除中断并获取中断状态 + + ///< TODO:根据中断状态发送数据 + ///< TODO:根据中断状态处理异常并执行用户回调函数 +} + +void dw_iic_rx_handler(void *arg) +{ + CSI_PARAM_CHK_NORETVAL(arg); + + ///< TODO:清除中断并获取中断状态 + + ///< TODO:根据中断状态接收数据 + ///< TODO:根据中断状态处理异常并执行用户回调函数 +} + +void dw_iic_slave_rx_handler(void *arg) +{ + CSI_PARAM_CHK_NORETVAL(arg); + + ///< TODO:清除中断并获取中断状态 + + ///< TODO:根据中断状态接收数据 + ///< TODO:根据中断状态处理异常并执行用户回调函数 + +} + +/** + \brief start slave mode dma send data + \param[in] iic handle of iic instance +*/ +void iic_slave_send_data_with_dma_irq(void *arg) +{ + CSI_PARAM_CHK_NORETVAL(arg); + + ///< TODO:清除中断并获取中断状态 + ///< TODO:清除IIC所有的中断 + ///< TODO:关闭IIC所有的中断 + + ///< TODO:根据中断状态用DMA模式发送数据 +} + +static void dw_iic_dma_event_cb(csi_dma_ch_t *dma, csi_dma_event_t event, void *arg) +{ + CSI_PARAM_CHK_NORETVAL(dma); + + ///< TODO:根据DMA传输的状态处理异常事件并调用用户回调函数 + ///< TODO:根据DMA传输的状态处理DMA传输完成事件并调用用户回调函数 +} +/** + \brief Init IIC ctrl block + 1. Initializes the resources needed for the IIC instance + 2.registers event callback function and user param for the callback + \param[in] iic handle of iic instance + \param[in] idx index of instance + \param[in] cb event callback function \ref csi_iic_event_cb_t + \param[in] arg user private param for event callback + \return \ref csi_error_t +*/ +csi_error_t csi_iic_init(csi_iic_t *iic, uint32_t idx) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< 获取中断号、基地址等相关信息 + ret = target_get(DEV_DW_IIC_TAG, idx, &iic->dev); + + if (ret == 0) { + ///< TODO:把IIC从机地址设置为0 + ///< TODO:关闭IIC + ///< TODO:清除IIC所有的中断 + ///< TODO:关闭IIC所有的中断 + ///< TODO:设置IIC从机在接收到来自主机的读取请求时不刷新FIFO中的数据 + } + + iic->state.writeable = 1U; + iic->state.readable = 1U; + iic->state.error = 0U; + iic->send = NULL; + iic->receive = NULL; + iic->rx_dma = NULL; + iic->tx_dma = NULL; + iic->callback = NULL; + + return ret; + +} + +/** + \brief De-initialize IIC Instanc + stops operation and releases the software resources used by the Instance + \param[in] iic handle of iic instance + \return \ref csi_error_t +*/ +void csi_iic_uninit(csi_iic_t *iic) +{ + CSI_PARAM_CHK_NORETVAL(iic); + + iic->state.error = 0U; + iic->state.writeable = 0U; + iic->state.readable = 0U; + iic->send = NULL; + iic->receive = NULL; + iic->rx_dma = NULL; + iic->tx_dma = NULL; + + ///< TODO:关闭IIC所有的中断 + ///< TODO:清除IIC所有的中断 + ///< TODO:关闭IIC + + // 禁止中断控制器对应的中断,注销中断服务函数 + csi_irq_disable((uint32_t)iic->dev.irq_num); + csi_irq_detach((uint32_t)iic->dev.irq_num); +} + +/** + \brief config iic master or slave mode + \param[in] iic handle of iic instance + \param[in] mode iic mode \ref csi_iic_mode_t + \return \ref csi_error_t +*/ +csi_error_t csi_iic_mode(csi_iic_t *iic, csi_iic_mode_t mode) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + csi_error_t ret = CSI_ERROR; + + if (mode == IIC_MODE_MASTER) { + iic->mode = IIC_MODE_MASTER; + + ///< TODO:设置IIC为主机模式 + + ret = CSI_OK; + } else if (mode == IIC_MODE_SLAVE) { + iic->mode = IIC_MODE_SLAVE; + + ///< TODO:设置IIC为从机模式 + + ret = CSI_OK; + } + + return ret; +} + +/** + \brief config iic addr mode + \param[in] iic handle of iic instance + \param[in] addr_mode iic addr mode + \return \ref csi_error_t +*/ +csi_error_t csi_iic_addr_mode(csi_iic_t *iic, csi_iic_addr_mode_t addr_mode) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + csi_error_t ret = CSI_ERROR; + + if (addr_mode == IIC_ADDRESS_7BIT) { + + ///< TODO:设置主机地址为7位 + ///< TODO:设置从机地址为7位 + + ret = CSI_OK; + } else if (addr_mode == IIC_ADDRESS_10BIT) { + + ///< TODO:设置主机地址为10位 + ///< TODO:设置从机地址为10位 + + ret = CSI_OK; + } + + return ret; +} + +/** + \brief config iic speed + \param[in] iic handle of iic instance + \param[in] speed iic speed mode + \return \ref csi_error_t +*/ +csi_error_t csi_iic_speed(csi_iic_t *iic, csi_iic_speed_t speed) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + csi_error_t ret = CSI_ERROR; + + if (speed == IIC_BUS_SPEED_STANDARD) { + + ///< TODO:设置IIC为标准模式,100KHZ + ///< TODO:获取IIC使用的频率 + ///< TODO:标准模式设置SCL时钟的高周期计数 + ///< TODO:标准模式设置SCL时钟的低周期计数 + + ret = CSI_OK; + } else if (speed == IIC_BUS_SPEED_FAST) { + + ///< TODO:设置IIC为快速模式,400KHz + ///< TODO:获取IIC使用的频率 + ///< TODO:快速模式设置SCL时钟的高周期计数 + ///< TODO:快速模式设置SCL时钟的低周期计数 + + ret = CSI_OK; + } else if (speed == IIC_BUS_SPEED_FAST_PLUS) { + ///< TODO:设置IIC为快速+模式,1MHz + ///< TODO:获取IIC使用的频率 + ///< TODO:快速模式+设置SCL时钟的高周期计数 + ///< TODO:快速模式+设置SCL时钟的低周期计数 + } else if (speed == IIC_BUS_SPEED_HIGH) { + + ///< TODO:设置IIC为高速模式,3.4MHz + ///< TODO:获取IIC使用的频率 + ///< TODO:高速模式设置SCL时钟的高周期计数 + ///< TODO:高速模式设置SCL时钟的低周期计数 + + ret = CSI_OK; + } + + return ret; +} + +/** + \brief config iic own addr + \param[in] iic handle of iic instance + \param[in] own_addr own addr + \return \ref csi_error_t +*/ +csi_error_t csi_iic_own_addr(csi_iic_t *iic, uint32_t own_addr) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< TODO:设置IIC从机的地址,注意该配置只在SLAVE模式下生效 + + return ret; +} + +/** + \brief Start sending data as IIC Master. + This function is blocking + \param[in] iic handle of iic instance + \param[in] devaddr addrress of slave device + \param[in] data data to send to IIC Slave + \param[in] size size of data items to send + \param[in] timout unit of time delay + \return master send real size and error code +*/ +int32_t csi_iic_master_send(csi_iic_t *iic, uint32_t devaddr, const void *data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + int32_t send_count = 0; + uint8_t *send_data = (void *)data; + + if ((send_data == NULL) || (size == 0U)) { + send_count = (int32_t)CSI_ERROR; + } else { + + ///< TODO:关闭IIC + ///< TODO:设置IIC从设备地址 + ///< TODO:打开IIC + ///< TODO:发送数据 + ///< TODO:超时则超时退出 + + } + + return send_count; +} + +/** + \brief Start receiving data as IIC Master. + This function is blocking + \param[in] iic handle to operate. + \param[in] devaddr iic addrress of slave device. + \param[out] data Pointer to buffer for data to receive from IIC receiver + \param[in] size size of data items to receive + \param[in] timeout unit of time delay + \return master receive real size and error code +*/ +int32_t csi_iic_master_receive(csi_iic_t *iic, uint32_t devaddr, void *data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + int32_t read_count = 0; + uint8_t *receive_data = (void *)data; + + if ((receive_data == NULL) || (size == 0U)) { + read_count = (int32_t)CSI_ERROR; + } else { + + ///< TODO:关闭IIC + ///< TODO:设置IIC从设备地址 + ///< TODO:打开IIC + + ///< TODO:配置IIC为接收数据 + ///< TODO:等待IIC接收数据,超时则超时退出 + ///< TODO:读数据寄存器接收数据 + + } + + return read_count; +} + +static csi_error_t iic_master_send_intr(csi_iic_t *iic, uint32_t devaddr, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + csi_error_t ret = CSI_OK; + + if ((data == NULL) || (size == 0U)) { + ret = CSI_ERROR; + } else { + if (iic->state.writeable == 0U) { + ret = CSI_BUSY; + } else { + + ///< TODO:设置IIC从设备地址 + + iic->data = (uint8_t *)data; + iic->size = size; + iic->state.writeable = 0U; + + ///< TODO:关闭IIC + ///< TODO:清除IIC所有的中断 + ///< TODO:关闭IIC所有的中断 + ///< TODO:使能发送中断 + ///< TODO:设置发送FIFO的触发级别 + ///< TODO:打开IIC + + } + } + + return ret; +} + +static csi_error_t iic_master_send_dma(csi_iic_t *iic, uint32_t devaddr, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + csi_error_t ret = CSI_OK; + + csi_dma_ch_config_t config; + memset(&config, 0, sizeof(csi_dma_ch_config_t)); + csi_dma_ch_t *dma_ch = (csi_dma_ch_t *)iic->tx_dma; + + iic->data = (void *)data; + iic->size = size; + iic->state.writeable = 0U; + + ///< TODO:关闭IIC + ///< TODO:清除IIC所有的中断 + ///< TODO:关闭IIC所有的中断 + ///< TODO:设置IIC从设备地址 + ///< TODO:使能IIC的DMA发送 + ///< TODO:设置DMA传输的触发级别 + + config.src_inc = DMA_ADDR_INC; + config.dst_inc = DMA_ADDR_CONSTANT; + config.src_tw = DMA_DATA_WIDTH_8_BITS; + config.dst_tw = DMA_DATA_WIDTH_8_BITS; + config.trans_dir = DMA_MEM2PERH; + config.handshake = iic_tx_hs_num[iic->dev.idx]; + + ///< 配置DMA通道 + csi_dma_ch_config(dma_ch, &config); + + soc_dcache_clean_invalid_range((unsigned long)iic->data, iic->size); + + ///< TODO:调用csi_dma_ch_start开启IIC使用的DMA通道 + ///< TODO:打开IIC + + return ret; +} + +/** + \brief Start sending data as IIC Master. + This function is non-blocking,\ref csi_iic_event_e is signaled when transfer completes or error happens. + \param[in] iic handle to operate. + \param[in] devaddr iic addrress of slave device. |_BIT[7:1]devaddr_|_BIT[0]R/W_| + eg: BIT[7:0] = 0xA0, devaddr = 0x50. + \param[in] data data to send to IIC Slave + \param[in] num size of data items to send + \return \ref csi_error_t +*/ +csi_error_t csi_iic_master_send_async(csi_iic_t *iic, uint32_t devaddr, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + csi_error_t ret = CSI_OK; + csi_iic_master_send_async_t send_func; + + if (iic->send) { + send_func = iic->send; + send_func(iic, devaddr, data, size); + } else { + ///< 注册发送中断服务函数、打开中断控制器对应的中断 + csi_irq_attach((uint32_t)iic->dev.irq_num, &dw_iic_tx_handler, &iic->dev); + csi_irq_enable((uint32_t)iic->dev.irq_num); + + ///< 开始IIC主机模式以中断方式发送数据 + iic_master_send_intr(iic, devaddr, data, size); + } + + return ret; +} + +static csi_error_t iic_master_receive_intr(csi_iic_t *iic, uint32_t devaddr, void *data, uint32_t size) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + csi_error_t ret = CSI_OK; + + if ((data == NULL) || (size == 0U)) { + ret = CSI_ERROR; + } else { + if (iic->state.readable == 0U) { + ret = CSI_BUSY; + } else { + + iic->data = (uint8_t *)data; + iic->size = size; + iic->state.readable = 0U; + unsigned long temp = size; + iic->priv = (void *)temp; ///< iic->priv used to record the transmission value + + ///< TODO:关闭IIC + ///< TODO:清除IIC所有的中断 + ///< TODO:关闭IIC所有的中断 + ///< TODO:设置IIC从设备地址 + ///< TODO:IIC使能主机接收中断 + ///< TODO:打开IIC + } + } + + return ret; +} + +/** + \brief Start receiving data as IIC Master. + This function is non-blocking,\ref csi_iic_event_t is signaled when transfer completes or error happens. + \ref csi_iic_get_status can get operating status. + \param[in] iic handle to operate. + \param[in] devaddr iic addrress of slave device. + \param[out] data pointer to buffer for data to receive from IIC receiver + \param[in] size size of data items to receive + \return \ref csi_error_t +*/ +csi_error_t csi_iic_master_receive_async(csi_iic_t *iic, uint32_t devaddr, void *data, uint32_t size) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + csi_error_t ret = CSI_OK; + /*the hardware only support master send with dma and master receive only use interrupt*/ + ///< 注册发送中断服务函数、打开中断控制器对应的中断 + csi_irq_attach((uint32_t)iic->dev.irq_num, &dw_iic_rx_handler, &iic->dev); + csi_irq_enable((uint32_t)iic->dev.irq_num); + + ///< 开始IIC主机模式以中断方式接收数据 + ret = iic_master_receive_intr(iic, devaddr, data, size); + return ret; +} + +/** + \brief Start transmitting data as IIC Master. + This function is blocking + \param[in] iic handle of iic instance + \param[in] devaddr addrress of slave device + \param[in] memaddr internal addr of device + \param[in] memaddr_size internal addr mode of device + \param[in] data data to send to IIC Slave + \param[in] size size of data items to send + \param[in] timout unit of time delay + \return memory send real size and error code +*/ +int32_t csi_iic_mem_send(csi_iic_t *iic, uint32_t devaddr, uint16_t memaddr, csi_iic_mem_addr_size_t memaddr_size, const void *data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + csi_error_t ret = CSI_OK; + int32_t send_count = 0; + uint8_t *send_data = (void *)data; + uint8_t mem_addr_flag = 1U; + uint8_t page_inx = 0U; + + if ((send_data == NULL) || (size == 0U)) { + send_count = (int32_t)CSI_ERROR; + } else { + + ///< TODO:关闭IIC + ///< TODO:设置IIC从设备地址 + ///< TODO:打开IIC + + if (memaddr_size == IIC_MEM_ADDR_SIZE_8BIT) { + + ///< TODO:IIC发送设备内部地址 + ///< TODO:等待发送完成,超时则超时退出 + + if (ret != CSI_OK) { + send_count = (int32_t)ret; + mem_addr_flag = 0U; + } + } + + if (memaddr_size == IIC_MEM_ADDR_SIZE_16BIT) { + + ///< TODO:IIC通过两次写数据寄存器发送设备内部16位的地址 + ///< TODO:等待发送完成,超时则超时退出 + + if (ret != CSI_OK) { + send_count = (int32_t)ret; + mem_addr_flag = 0U; + } + } + + while (mem_addr_flag) { + + ///< TODO:IIC发送数据 + ///< TODO:等待发送完成,超时则超时退出 + + if (ret != CSI_OK) { + send_count = (int32_t)ret; + break; + } + + send_count ++; + page_inx ++; + + if ((page_inx == IIC_EEPROM_MAX_WRITE_LEN) && (send_count != (int32_t)size)) { + page_inx = 0U; + memaddr = memaddr + IIC_EEPROM_MAX_WRITE_LEN; + + if (memaddr_size == IIC_MEM_ADDR_SIZE_8BIT) { + + ///< TODO:IIC发送设备内部地址 + ///< TODO:等待发送完成,超时则超时退出 + + if (ret != CSI_OK) { + send_count = (int32_t)ret; + mem_addr_flag = 0U; + } + } + + if (memaddr_size == IIC_MEM_ADDR_SIZE_16BIT) { + + ///< TODO:IIC通过两次写数据寄存器发送设备内部16位的地址 + ///< TODO:等待发送完成,超时则超时退出 + + if (ret != CSI_OK) { + send_count = (int32_t)ret; + mem_addr_flag = 0U; + } + } + + } + + } + } + + return send_count; +} + +/** + \brief Start receiving data as IIC Master. + This function is blocking + \param[in] iic handle to operate. + \param[in] devaddr iic addrress of slave device. + \param[in] memaddr internal addr of device + \param[in] memaddr_mode internal addr mode of device + \param[out] data Pointer to buffer for data to receive from IIC receiver + \param[in] size size of data items to receive + \param[in] timeout unit of time delay + \return memory receive real size and error code +*/ +int32_t csi_iic_mem_receive(csi_iic_t *iic, uint32_t devaddr, uint16_t memaddr, csi_iic_mem_addr_size_t memaddr_size, void *data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + csi_error_t ret = CSI_OK; + int32_t read_count = 0; + uint8_t *receive_data = (void *)data; + uint8_t mem_addr_flag = 1U; + + if ((receive_data == NULL) || (size == 0U)) { + read_count = (int32_t)CSI_ERROR; + } else { + + ///< TODO:关闭IIC + ///< TODO:设置IIC从设备地址 + ///< TODO:打开IIC + + if (memaddr_size == IIC_MEM_ADDR_SIZE_8BIT) { + + ///< TODO:IIC发送设备内部地址 + ///< TODO:等待发送完成,超时则超时退出 + + if (ret != CSI_OK) { + mem_addr_flag = 0U; + } + } + + if (memaddr_size == IIC_MEM_ADDR_SIZE_16BIT) { + + ///< TODO:IIC通过两次写数据寄存器发送设备内部16位的地址 + ///< TODO:等待发送完成,超时则超时退出 + + if (ret != CSI_OK) { + mem_addr_flag = 0U; + } + } + + uint32_t cmd_num; + + if (mem_addr_flag == 1U) { + if (size < IIC_MAX_FIFO) { + for (read_count = 0; read_count < (int32_t)size; read_count++) { + ///< TODO:设置IIC为接收数据模式 + } + + ///< TODO:等待接收数据,超时则超时退出 + + if (ret == CSI_OK) { + for (read_count = 0; read_count < (int32_t)size; read_count++) { + ///< TODO:IIC读数据寄存器接收数据 + } + } else { + read_count = (int32_t)ret; + } + + } else { + read_count = 0; + + for (cmd_num = size; cmd_num > (size - IIC_MAX_FIFO); cmd_num--) { + ///< TODO:设置IIC为接收数据模式 + } + + while (mem_addr_flag) { + + ///< TODO:等待接收数据,超时则超时退出 + + if (ret != CSI_OK) { + read_count = (int32_t)ret; + break; + } + + ///< TODO:IIC读数据寄存器接收数据 + + read_count ++; + + if (cmd_num > 0U) { + + ///< TODO:设置IIC为接收数据模式 + + cmd_num --; + } + } + } + } else { + read_count = (int32_t)CSI_ERROR; + } + + } + + return read_count; +} + +/** + \brief Start sending data as IIC Slave. + This function is blocking + \param[in] iic handle to operate. + \param[in] data Pointer to buffer with data to transmit to IIC Master + \param[in] size size of data items to send + \param[in] timeout uint in mini-second + \return slave send real size and error code +*/ +int32_t csi_iic_slave_send(csi_iic_t *iic, const void *data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + int32_t send_count = 0; + uint8_t *send_data = (void *)data; + + if ((send_data == NULL) || (size == 0U)) { + send_count = (int32_t)CSI_ERROR; + } else { + + ///< TODO:打开IIC + ///< TODO:超时则退出 + ///< TODO:获取原始中断的状态 + ///< TODO:根据中断的状态IIC写数据寄存器发送数据 + ///< TODO:等待发送完成,超时则超时退出 + } + + return send_count; +} + +/** + \brief Start receiving data as IIC Slave. + This function is blocking + \param[in] iic handle to operate. + \param[out] data Pointer to buffer for data to receive from IIC Master + \param[in] size size of data items to receive + \param[in] timeout uint in mini-second + \return slave receive real size and error code +*/ +int32_t csi_iic_slave_receive(csi_iic_t *iic, void *data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + csi_error_t ret = CSI_OK; + int32_t read_count = 0; + uint8_t *receive_data = (void *)data; + + if ((receive_data == NULL) || (size == 0U)) { + read_count = (int32_t)CSI_ERROR; + } else { + + ///< TODO:打开IIC + + while (1) { + ///< TODO:等待接收数据,超时则超时退出 + + if (ret != CSI_OK) { + read_count = (int32_t)ret; + break; + } + + ///< TODO:IIC读数据寄存器发送数据 + read_count ++; + + if (read_count == (int32_t)size) { + break; + } + } + } + + return read_count; +} + +static csi_error_t iic_slave_send_dma(csi_iic_t *iic, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + csi_error_t ret = CSI_OK; + + csi_dma_ch_config_t config; + memset(&config, 0, sizeof(csi_dma_ch_config_t)); + csi_dma_ch_t *dma_ch = (csi_dma_ch_t *)iic->tx_dma; + + iic->data = (void *)data; + iic->size = size; + iic->state.writeable = 0U; + + ///< TODO:关闭IIC + ///< TODO:清除IIC所有的中断 + ///< TODO:关闭IIC所有的中断 + ///< TODO:IIC从机使能发送中断 + + ///< 注册DMA发送完成中断服务函数、打开中断控制器对应的中断 + csi_irq_attach((uint32_t)iic->dev.irq_num, &iic_slave_send_data_with_dma_irq, &iic->dev); ///< if use slave send dma attach will change + csi_irq_enable((uint32_t)iic->dev.irq_num); + + config.src_inc = DMA_ADDR_INC; + config.dst_inc = DMA_ADDR_CONSTANT; + config.src_tw = DMA_DATA_WIDTH_8_BITS; + config.dst_tw = DMA_DATA_WIDTH_8_BITS; + config.trans_dir = DMA_MEM2PERH; + config.handshake = iic_tx_hs_num[iic->dev.idx]; + + ///< 配置DMA通道 + csi_dma_ch_config(dma_ch, &config); + + ///< TODO:打开IIC + + return ret; +} + +static csi_error_t iic_slave_send_intr(csi_iic_t *iic, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + csi_error_t ret = CSI_OK; + + if ((data == NULL) || (size == 0U)) { + ret = CSI_ERROR; + } else { + if (iic->state.writeable == 0U) { + ret = CSI_BUSY; + } else { + + iic->data = (uint8_t *)data; + iic->size = size; + iic->state.writeable = 0U; + + ///< TODO:关闭IIC + ///< TODO:清除IIC所有的中断 + ///< TODO:关闭IIC所有的中断 + ///< TODO:IIC从机使能发送中断 + ///< TODO:打开IIC + } + } + + return ret; +} + +/** +\brief Start transmitting data as IIC Slave. + This function is non-blocking,\ref csi_iic_event_t is signaled when transfer completes or error happens. +\param[in] iic handle to operate. +\param[in] data Pointer to buffer with data to transmit to IIC Master +\param[in] size size of data items to send +\return \ref csi_error_t +*/ +csi_error_t csi_iic_slave_send_async(csi_iic_t *iic, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + csi_error_t ret = CSI_OK; + csi_iic_slave_send_async_t send_func; + + if (iic->send) { + send_func = iic->send; + ///< 注册发送中断服务函数、使能中断控制器对应的中断 + csi_irq_attach((uint32_t)iic->dev.irq_num, &iic_slave_send_data_with_dma_irq, &iic->dev); + csi_irq_enable((uint32_t)iic->dev.irq_num); + send_func(iic, data, size); + } else { + ///< 注册发送中断服务函数、使能中断控制器对应的中断 + csi_irq_attach((uint32_t)iic->dev.irq_num, &dw_iic_slave_tx_handler, &iic->dev); + csi_irq_enable((uint32_t)iic->dev.irq_num); + + ///< 开始IIC从机模式以中断方式发送数据 + iic_slave_send_intr(iic, data, size); + } + + return ret; +} + +static csi_error_t iic_slave_receive_intr(csi_iic_t *iic, void *data, uint32_t size) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + csi_error_t ret = CSI_OK; + + if ((data == NULL) || (size == 0U)) { + ret = CSI_ERROR; + } else { + if (iic->state.readable == 0U) { + ret = CSI_BUSY; + } else { + + iic->data = (uint8_t *)data; + iic->size = size; + iic->state.readable = 0U; + + ///< TODO:关闭IIC + ///< TODO:清除IIC所有的中断 + ///< TODO:关闭IIC所有的中断 + ///< TODO:使能IIC从机接收中断 + + ///< TODO:打开IIC + } + } + + return ret; +} + +static csi_error_t iic_slave_receive_dma(csi_iic_t *iic, void *data, uint32_t size) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + csi_error_t ret = CSI_OK; + + csi_dma_ch_config_t config; + memset(&config, 0, sizeof(csi_dma_ch_config_t)); + csi_dma_ch_t *dma = (csi_dma_ch_t *)iic->rx_dma; + + iic->data = (uint8_t *)data; + iic->size = size; + iic->state.readable = 0U; + + ///< TODO:关闭IIC + ///< TODO:清除IIC所有的中断 + ///< TODO:关闭IIC所有的中断 + ///< TODO:IIC DMA接收模式的使能 + ///< TODO:设置IIC DMA模式接收数据的触发级别 + + config.src_inc = DMA_ADDR_CONSTANT; + config.dst_inc = DMA_ADDR_INC; + config.src_tw = DMA_DATA_WIDTH_8_BITS; + config.dst_tw = DMA_DATA_WIDTH_8_BITS; + config.trans_dir = DMA_PERH2MEM; + config.handshake = iic_rx_hs_num[iic->dev.idx]; + + ///< 配置DMA通道 + csi_dma_ch_config(dma, &config); + + soc_dcache_clean_invalid_range((unsigned long)iic->data, iic->size); + + ///< TODO:调用csi_dma_ch_start开启IIC使用的DMA的通道 + ///< TODO:打开IIC + + return ret; +} + +/** +\brief Start receiving data as IIC Slave. + This function is non-blocking,\ref iic_event_e is signaled when transfer completes or error happens. +\param[in] handle iic handle to operate. +\param[out] data Pointer to buffer for data to receive from IIC Master +\param[in] size size of data items to receive +\return \ref csi_error_t +*/ +csi_error_t csi_iic_slave_receive_async(csi_iic_t *iic, void *data, uint32_t size) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + csi_error_t ret = CSI_OK; + csi_iic_slave_receive_async_t receive_func; + + if (iic->receive) { + receive_func = iic->receive; + receive_func(iic, data, size); + } else { + ///< 初始化接收中断服务函数、使能中断控制器对应的中断 + csi_irq_attach((uint32_t)iic->dev.irq_num, &dw_iic_slave_rx_handler, &iic->dev); + csi_irq_enable((uint32_t)iic->dev.irq_num); + + ///< TODO:开始IIC从机模式以中断方式发送数据 + iic_slave_receive_intr(iic, data, size); + } + + return ret; +} + +/** +\brief Attach callback to the iic +\param[in] iic iic handle to operate. +\param[in] cb event callback function \ref csi_iic_callback_t +\param[in] arg user private param for event callback +\return \ref csi_error_t +*/ +csi_error_t csi_iic_attach_callback(csi_iic_t *iic, void *callback, void *arg) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + csi_error_t ret = CSI_OK; + iic->callback = callback; + iic->arg = arg; + return ret; +} + +/** +\brief detach callback from the iic +\param[in] iic iic handle to operate. +*/ +void csi_iic_detach_callback(csi_iic_t *iic) +{ + CSI_PARAM_CHK_NORETVAL(iic); + iic->callback = NULL; + iic->arg = NULL; + iic->send = NULL; + iic->receive = NULL; + ///< 禁止中断控制器对应的中断、注销中断服务函数 + csi_irq_disable((uint32_t)iic->dev.irq_num); + csi_irq_detach((uint32_t)iic->dev.irq_num); +} + +/** +\brief config iic stop to generate +\param[in] iic iic handle to operate. +\param[in] enable Transfer operation is pending - Stop condition will not be generated. +\return \ref csi_error_t +*/ +csi_error_t csi_iic_xfer_pending(csi_iic_t *iic, bool enable) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + csi_error_t ret = CSI_UNSUPPORTED; + return ret; +} + +/** + \brief link DMA channel to iic device + \param[in] iic handle to operate. + \param[in] tx_dma the DMA channel handle for send, when it is NULL means to unlink the channel + \param[in] rx_dma the DMA channel handle for receive, when it is NULL means to unlink the channel + \return error code +*/ +csi_error_t csi_iic_link_dma(csi_iic_t *iic, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + csi_error_t ret = CSI_ERROR; + + if (iic->callback != NULL) { + if (iic->mode == IIC_MODE_MASTER) { + /*the hardware only support master send with dma and master receive only use interrupt*/ + if (tx_dma != NULL) { + tx_dma->parent = iic; + ///< 申请DMA通道 + ret = csi_dma_ch_alloc(tx_dma, -1, -1); + + if (ret == CSI_OK) { + ///< 注册DMA中断服务函数 + csi_dma_ch_attach_callback(tx_dma, dw_iic_dma_event_cb, NULL); + iic->tx_dma = tx_dma; + ///< 注册IIC主机模式以DMA模式发送数据函数 + iic->send = iic_master_send_dma; + } else { + tx_dma->parent = NULL; + } + } else { + if (iic->tx_dma) { + ///< 注销DMA中断服务函数和释放DMA通道 + csi_dma_ch_detach_callback(iic->tx_dma); + csi_dma_ch_free(iic->tx_dma); + ///< 注册IIC主机模式以中断模式发送数据函数 + iic->send = iic_master_send_intr; + iic->tx_dma = NULL; + } + + ret = CSI_OK; + } + } else if (iic->mode == IIC_MODE_SLAVE) { + /*the hardware only support slave receive with dma and slave send only use interrupt*/ + if (tx_dma != NULL) { + tx_dma->parent = iic; + ///< 申请DMA通道 + ret = csi_dma_ch_alloc(tx_dma, -1, -1); + + if (ret == CSI_OK) { + ///< 注册DMA中断服务函数 + csi_dma_ch_attach_callback(tx_dma, dw_iic_dma_event_cb, NULL); + iic->tx_dma = tx_dma; + ///< 注册IIC主机模式以DMA模式发送数据函数 + iic->send = iic_slave_send_dma; + } else { + tx_dma->parent = NULL; + } + } else { + if (iic->tx_dma) { + ///< 注销DMA中断服务函数和释放DMA通道 + csi_dma_ch_detach_callback(iic->tx_dma); + csi_dma_ch_free(iic->tx_dma); + ///< 注册IIC从机模式以中断模式发送数据函数 + iic->send = iic_slave_send_intr; + iic->tx_dma = NULL; + } + + ret = CSI_OK; + } + + if (rx_dma != NULL) { + rx_dma->parent = iic; + ///< 申请DMA通道 + ret = csi_dma_ch_alloc(rx_dma, -1, -1); + + if (ret == CSI_OK) { + iic->rx_dma = rx_dma; + ///< 注册DMA中断服务函数 + csi_dma_ch_attach_callback(rx_dma, dw_iic_dma_event_cb, NULL); + ///< 注册IIC从机模式以DMA模式发送数据函数 + iic->receive = iic_slave_receive_dma; + } else { + rx_dma->parent = NULL; + } + } else { + if (iic->rx_dma) { + ///< 注销DMA中断服务函数和释放DMA通道 + csi_dma_ch_detach_callback(iic->rx_dma); + csi_dma_ch_free(iic->rx_dma); + ///< 注册IIC从机模式以中断模式发送数据函数 + iic->receive = iic_slave_receive_intr; + iic->rx_dma = NULL; + } + + ret = CSI_OK; + } + } + } + + return ret; +} + +/** +\brief start receiving data as IIC Slave. + This function is non-blocking,\ref iic_event_e is signaled when transfer completes or error happens. +\param[in] iic handle to operate. +\param[out] state iic state \ref csi_state_t +\return \ref csi_error_t +*/ +csi_error_t csi_iic_get_state(csi_iic_t *iic, csi_state_t *state) +{ + CSI_PARAM_CHK(iic, CSI_ERROR); + CSI_PARAM_CHK(state, CSI_ERROR); + *state = iic->state; + return CSI_OK; +} + +#ifdef CONFIG_PM +static csi_error_t dw_iic_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action) +{ + CSI_PARAM_CHK(dev, CSI_ERROR); + + csi_error_t ret = CSI_OK; + csi_pm_dev_t *pm_dev = &dev->pm_dev; + + switch (action) { + case PM_DEV_SUSPEND: + ///< TODO:恢复IIC寄存器 + break; + + case PM_DEV_RESUME: + ///< TODO:保存IIC寄存器 + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +csi_error_t csi_iic_enable_pm(csi_iic_t *iic) +{ + ///< TODO:注册IIC低功耗处理函数dw_iic_pm_action +} + +void csi_iic_disable_pm(csi_iic_t *iic) +{ + csi_pm_dev_unregister(&iic->dev); +} +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/mbox.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/mbox.c new file mode 100644 index 00000000000..f0b86d730cb --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/mbox.c @@ -0,0 +1,213 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include + +#define CHN_NUM 4 +#define INFO_NUM 8 +#define MBOX_SEND_MAX_MESSAGE_LENGTH ((INFO_NUM - 1U) * 4U) + +/** + \brief wj_box_irq_handler + \param[in] mbox handle of mbox instance +*/ +static void wj_mbox_irq_handler(void *arg) +{ + CSI_PARAM_CHK_NORETVAL(arg); + + ///< TODO:获取中断状态 + ///< TODO:清除中断 + ///< TODO:根据中断状态处理中断 + +} + +/** + \brief Initialize MAILBOX Interface. 1. Initializes the resources needed for the MAILBOX interface 2.registers event callback function + \param[in] mbox operate handle + \param[in] idx the device idx + \return error code +*/ +csi_error_t csi_mbox_init(csi_mbox_t *mbox, uint32_t idx) +{ + CSI_PARAM_CHK(mbox, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< 获取中断号、基地址等相关信息 + ret = target_get(DEV_WJ_MBOX_TAG, idx, &mbox->dev); + + if (ret == CSI_OK) { + + for (uint32_t i = 0U; i < CHN_NUM; i++) { + for (uint32_t j = 0U; j < INFO_NUM; j++) { + /// TODO:把CPU0所有通道的MBOX_INFO清零 + } + + ///< TODO:屏蔽CPU0所有通道的中断 + } + + for (uint32_t i = 0U; i < CHN_NUM; i++) { + ///< TODO:不屏蔽CPU0所有通道的中断 + ///< TODO:清除CPU0所有通道的中断 + } + } + + return ret; +} + +/** + \brief De-initialize MAILBOX Interface. stops operation and releases the software resources used by the interface + \param[in] mbox operate handle +*/ +void csi_mbox_uninit(csi_mbox_t *mbox) +{ + CSI_PARAM_CHK_NORETVAL(mbox); + + for (uint32_t i = 0U; i < CHN_NUM; i++) { + + ///< TODO:屏蔽CPU0所有通道的读中断 + ///< TODO:清除CPU0所有通道的中断 + + } + + ///< 注销MBOX中断服务函数,禁止中断控制器中对应的中断 + csi_irq_detach((uint32_t)mbox->dev.irq_num); + csi_irq_disable((uint32_t)mbox->dev.irq_num); +} + +/** + \brief Start sending data to MAILBOX transmitter,(received data is ignored). + This function is non-blocking,\ref mailbox_event_e is signaled when operation completes or error happens. + \ref csi_mailbox_get_status can get operation status. + \param[in] mbox operate handle + \param[in] channel_id index of channel + \param[in] data Pointer to buffer with data to send to MAILBOX transmitter. + \param[in] size size of data items to send + \return sent number of data +*/ +int32_t csi_mbox_send(csi_mbox_t *mbox, uint32_t channel_id, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(mbox, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + csi_error_t ret = CSI_OK; + + int32_t tx_len = (size > MBOX_SEND_MAX_MESSAGE_LENGTH) ? (int32_t)MBOX_SEND_MAX_MESSAGE_LENGTH : (int32_t)size; + + ///< TODO:获取某个CPU的某个通道 + + if (ret == CSI_OK) { + uint32_t mbox_busy = 0; + ///< TODO:获取指定的CPU以及该CPU的某个通道的繁忙状态到mbox_busy + + if (mbox_busy & 0x1U) { + tx_len = 0; + } else { + uint32_t buf[(MBOX_SEND_MAX_MESSAGE_LENGTH + 3U) >> 2U] = {0U}; + uint32_t gen_interrupt = 0U; + memcpy(&buf, data, (uint32_t)tx_len); + + for (uint32_t count = (uint32_t)(((uint32_t)tx_len + 3U) / 4U); count > 0U; count--) { + ///< TODO:往指定的CPU以及该CPU的某个通道写数据(buf[count - 1U]) + gen_interrupt += (uint32_t)((uint32_t)1U << (count - 1U)); + } + + /* send tx_len to target channel */ + ///< TODO:往指定的CPU以及该CPU的某个通道写数据((uint32_t)(((uint32_t)tx_len & 0xfffU) << 4U)) + + ///< TODO:使能指定的CPU以及该CPU的某个通道的中断 + } + + } else { + tx_len = -1; + } + + return tx_len; +} + +/** + \brief Start Receiving data from Mailbox receiver. + \param[in] mbox operate handle. + \param[in] channel_id index of channel + \param[out] data Pointer to buffer with data to receive from mailbox. + \param[in] size Number of data items to receive + \return received number or error code +*/ +int32_t csi_mbox_receive(csi_mbox_t *mbox, uint32_t channel_id, void *data, uint32_t size) +{ + CSI_PARAM_CHK(mbox, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + int32_t rx_len = (int32_t)size; + + uint32_t buf[(MBOX_SEND_MAX_MESSAGE_LENGTH + 3U) >> 2U] = {0U}; + + ///< TODO:获取某个CPU的某个通道 + + if (channel_id < CHN_NUM) { + for (uint32_t i = 0U; i < ((size + 3U) >> 2U); i++) { + ///< TODO:获取数据到buf[i] + ///< TODO:往指定的CPU以及该CPU的某个通道写数据(0) + } + + ///< TODO:禁止指定的CPU以及该CPU的某个通道的中断 + memcpy(data, buf, size); + + ///< TODO:往指定的CPU以及该CPU的某个通道写数据((MBOX_ACK << 16U) | 1U) + ///< TODO:使能指定的CPU以及该CPU的某个通道的中断 + } else { + rx_len = -1; + } + + return rx_len; +} + +/** +\brief Attach callback to the mbox +\param[in] mbox operate handle. +\param[in] cb event callback function \ref csi_mbox_callback_t +\param[in] arg user private param for event callback +\return error code +*/ +csi_error_t csi_mbox_attach_callback(csi_mbox_t *mbox, void *callback, void *arg) +{ + CSI_PARAM_CHK(mbox, CSI_ERROR); + CSI_PARAM_CHK(callback, CSI_ERROR); + csi_error_t ret = CSI_OK; + mbox->callback = callback; + mbox->arg = arg; + ///< TODO:注册MBOX中断服务函数,使能中断控制器对应的中断 + csi_irq_attach((uint32_t)mbox->dev.irq_num, &wj_mbox_irq_handler, &mbox->dev); + csi_irq_enable((uint32_t)mbox->dev.irq_num); + return ret; +} + +/** +\brief detach callback from the mbox +\param[in] mbox operate handle. +*/ +void csi_mbox_detach_callback(csi_mbox_t *mbox) +{ + CSI_PARAM_CHK_NORETVAL(mbox); + mbox->callback = NULL; + mbox->arg = NULL; + ///< TODO:注销MBOX的中断服务函数,禁止中断控制器对应的中断 + csi_irq_detach((uint32_t)mbox->dev.irq_num); + csi_irq_disable((uint32_t)mbox->dev.irq_num); +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/pinmux.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/pinmux.c new file mode 100644 index 00000000000..22e3e676b85 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/pinmux.c @@ -0,0 +1,78 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file pinmux.c + * @brief source file for the pinmux + * @version V1.0 + * @date 02. June 2017 + ******************************************************************************/ + +#include +#include +#include +#include +#include "soc.h" + +/******************************************************************************* + * function: ioreuse config + *******************************************************************************/ +csi_error_t csi_pin_set_mux(pin_name_t pin_name, pin_func_t pin_func) +{ + return CSI_OK; +} + + +csi_error_t csi_pin_mode(pin_name_t pin_name, csi_gpio_mode_t mode) +{ + return CSI_OK; +} + + +/** + \brief get the pin function. + \param[in] pin refs to pin_name_e. + \return pin function count +*/ +pin_func_t csi_pin_get_mux(pin_name_t pin_name) +{ + return PIN_FUNC_GPIO; +} + +/** + \brief set pin speed + \param[in] pin_name pin name, defined in soc.h. + \param[in] speed io speed + \return error code +*/ +csi_error_t csi_pin_speed(pin_name_t pin_name, csi_pin_speed_t speed) +{ + return CSI_OK; +} + + +/** + \brief set pin drive + \param[in] pin_name pin name, defined in soc.h. + \param[in] drive io drive + \return error code +*/ +csi_error_t csi_pin_drive(pin_name_t pin_name, csi_pin_drive_t drive) +{ + return CSI_OK; +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/power_manage.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/power_manage.c new file mode 100644 index 00000000000..3f807880864 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/power_manage.c @@ -0,0 +1,292 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file power_manage.c + * @brief CSI Source File for power manage + * @version V1.0 + * @date 16. Mar 2020 + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PM +#include + +#define NODE_USED_MASK 0x00000001U + +#ifndef CONFIG_PM_DEV_PRIORITY +#define CONFIG_PM_DEV_PRIORITY 4 +#endif + +typedef struct reten_mem_node { + struct reten_mem_node *next; + uint32_t size; +} reten_mem_node_t; + +static slist_t pm_dev_list[CONFIG_PM_DEV_PRIORITY]; +static uint32_t *pm_dev_reten_mem; + +csi_error_t csi_pm_init(void) +{ + for (uint8_t i = 0; i < CONFIG_PM_DEV_PRIORITY; i++) { + slist_init(&pm_dev_list[i]); + } + + return CSI_OK; +} + +void csi_pm_uninit(void) +{ + for (uint8_t i = 0; i < CONFIG_PM_DEV_PRIORITY; i++) { + slist_init(&pm_dev_list[i]); + } +} + +csi_error_t csi_pm_set_reten_mem(uint32_t *mem, uint32_t num) +{ + CSI_PARAM_CHK(mem, CSI_ERROR); + + csi_error_t ret = CSI_OK; + reten_mem_node_t *node; + + if (num >= 3U) { + pm_dev_reten_mem = mem; + + node = (reten_mem_node_t *)mem; + node->next = NULL; + node->size = num * 4U - 8U; + } else { + ret = CSI_ERROR; + } + + return ret; +} + +static uint32_t *pm_alloc_reten_mem(uint32_t size) +{ + int32_t found = 0; + uint32_t *mem = NULL; + reten_mem_node_t *node = (reten_mem_node_t *)pm_dev_reten_mem; + + while (node) { + if (node->size == size) { + found = 1; + node->size |= NODE_USED_MASK; + mem = (uint32_t *)((uint32_t)node + 8U); + break; + } + + node = node->next; + } + + if (found == 0) { + node = (reten_mem_node_t *)pm_dev_reten_mem; + + while (node) { + if (node->size > size && !(node->size & NODE_USED_MASK)) { + if (node->size >= size + 12U) { + reten_mem_node_t *newnode; + newnode = (reten_mem_node_t *)((uint32_t)node + 8U + size); + newnode->size = node->size - size - 8U; + newnode->next = node->next; + node->next = newnode; + node->size = (size | NODE_USED_MASK); + } else { + node->size |= NODE_USED_MASK; + } + + mem = (uint32_t *)((uint32_t)node + 8U); + break; + } + + node = node->next; + } + } + + return mem; +} + +static void pm_free_reten_mem(uint32_t *mem) +{ + reten_mem_node_t *node = (reten_mem_node_t *)pm_dev_reten_mem; + + while (node) { + uint32_t addr; + addr = (uint32_t)node + 8U; + + if (addr == (uint32_t)mem) { + node->size &= ~NODE_USED_MASK; + break; + } + + node = node->next; + } +} + +csi_error_t csi_pm_dev_register(csi_dev_t *dev, void *pm_action, uint32_t mem_size, uint8_t priority) +{ + CSI_PARAM_CHK(dev, CSI_ERROR); + + csi_error_t ret = CSI_OK; + uint32_t *mem = NULL; + + dev->pm_dev.pm_action = pm_action; + dev->pm_dev.size = mem_size; + + slist_add(&dev->pm_dev.next, &pm_dev_list[priority]); + + mem = pm_alloc_reten_mem(dev->pm_dev.size); + dev->pm_dev.reten_mem = mem; + + if (mem == NULL) { + ret = CSI_ERROR; + } + + return ret; +} + +void csi_pm_dev_unregister(csi_dev_t *dev) +{ + CSI_PARAM_CHK_NORETVAL(dev); + + for (uint8_t i = 0; i < CONFIG_PM_DEV_PRIORITY; i++) { + slist_del(&dev->pm_dev.next, &pm_dev_list[i]); + } + + pm_free_reten_mem(dev->pm_dev.reten_mem); +} + +void csi_pm_dev_save_regs(uint32_t *mem, uint32_t *addr, uint32_t num) +{ + for (uint32_t i = 0U; i < num; i++) { + mem[i] = addr[i]; + } +} + +void csi_pm_dev_restore_regs(uint32_t *mem, uint32_t *addr, uint32_t num) +{ + for (uint32_t i = 0U; i < num; i++) { + addr[i] = mem[i]; + } +} + +csi_error_t csi_pm_dev_notify(csi_pm_dev_action_t action) +{ + csi_error_t ret = CSI_OK; + csi_pm_dev_t *node; + csi_dev_t *dev; + uint32_t flags; + int8_t i; + + flags = csi_irq_save(); + + if (action == PM_DEV_SUSPEND) { + for (i = CONFIG_PM_DEV_PRIORITY - 1; i >= 0; i--) { + slist_for_each_entry(&pm_dev_list[i], node, csi_pm_dev_t, next) { + if (node) { + dev = (csi_dev_t *)((uint32_t)node - 12U); + ret = node->pm_action(dev, action); + + if (ret != CSI_OK) { + break; + } + } + } + } + } else { + for (i = 0; i < CONFIG_PM_DEV_PRIORITY; i++) { + slist_for_each_entry(&pm_dev_list[i], node, csi_pm_dev_t, next) { + if (node) { + dev = (csi_dev_t *)((uint32_t)node - 12U); + ret = node->pm_action(dev, action); + + if (ret != CSI_OK) { + break; + } + } + } + } + } + + csi_irq_restore(flags); + + return ret; +} + +csi_error_t csi_pm_enter_sleep(csi_pm_mode_t mode) +{ + csi_error_t ret = CSI_OK; + + switch (mode) { + case PM_MODE_SLEEP_1: + break; + + case PM_MODE_SLEEP_2: + break; + + case PM_MODE_DEEP_SLEEP_1: + ret = csi_pm_dev_notify(PM_DEV_SUSPEND); + break; + + case PM_MODE_DEEP_SLEEP_2: + break; + + default: + break; + } + + if (ret == CSI_OK) { + ret = soc_pm_enter_sleep(mode); + + switch (mode) { + case PM_MODE_SLEEP_1: + break; + + case PM_MODE_SLEEP_2: + break; + + case PM_MODE_DEEP_SLEEP_1: + ret = csi_pm_dev_notify(PM_DEV_RESUME); + break; + + case PM_MODE_DEEP_SLEEP_2: + break; + + default: + break; + } + } + + return ret; +} + +csi_error_t csi_pm_config_wakeup_source(uint32_t wakeup_num, bool enable) +{ + csi_error_t ret = CSI_OK; + + ret = soc_pm_config_wakeup_source(wakeup_num, enable); + + return ret; +} +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/pwm.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/pwm.c new file mode 100644 index 00000000000..9f073473c79 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/pwm.c @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + */ + +/******************************************************* + * @file pwm.c + * @brief source file for pwm csi driver + * @version V2.0 + * @date 23. Sep 2020 + * ******************************************************/ + +#include +#include + +/** + \brief PWM interrupt handling function + \param[in] arg Callback function member variables + \return None +*/ +void wj_pwm_irq_handler(void *arg) +{ + + ///< TODO:判断中断是否发生 + ///< TODO:如果发生了则清除中断 + ///< TODO:如果发生处理中断 + +} + +/** + \brief Initialize PWM Interface. 1. Initializes the resources needed for the PWM interface + \param[in] pwm pwm handle to operate + \param[in] idx pwm idx + \return error code +*/ +csi_error_t csi_pwm_init(csi_pwm_t *pwm, uint32_t idx) +{ + CSI_PARAM_CHK(pwm, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< 初始化PWM控制器 + + ///< 获取中断号、基地址等相关信息 + if (0 == target_get(DEV_WJ_PWM_TAG, idx, &pwm->dev)) { + + ///< TODO:把PWM相关寄存器复位清零 + + } else { + ret = CSI_ERROR; + } + + return ret; +} + +/** + \brief De-initialize PWM Interface. stops operation and releases the software resources used by the interface + \param[in] pwm pwm handle to operate + \return None +*/ +void csi_pwm_uninit(csi_pwm_t *pwm) +{ + CSI_PARAM_CHK_NORETVAL(pwm); + + ///< TODO:把PWM相关寄存器复位清零 + +} + +/** + \brief Config pwm out mode + \param[in] pwm pwm handle to operate + \param[in] channel channel num + \param[in] period_us the PWM period in us + \param[in] pulse_width_us the PMW pulse width in us + \param[in] polarity the PWM polarity \ref csi_pwm_polarity_t + \return error code +*/ +csi_error_t csi_pwm_out_config(csi_pwm_t *pwm, + uint32_t channel, + uint32_t period_us, + uint32_t pulse_width_us, + csi_pwm_polarity_t polarity) +{ + CSI_PARAM_CHK(pwm, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< TODO:检查参数channel的正确性 + + ///< TODO:设置PWM通道的模式 + ///< TODO:根据period_us、pulse_width_us设置PWM的占空比 + + return ret; +} + +/** + \brief Start generate pwm signal + \param[in] pwm pwm handle to operate + \param[in] channel channel num + \return error code +*/ +csi_error_t csi_pwm_out_start(csi_pwm_t *pwm, uint32_t channel) +{ + CSI_PARAM_CHK(pwm, CSI_ERROR); + + ///< TODO:打开输出使能 + + return CSI_OK; +} + +/** + \brief Stop generate pwm signal + \param[in] pwm pwm handle to operate + \param[in] channel channel num + \return None +*/ +void csi_pwm_out_stop(csi_pwm_t *pwm, uint32_t channel) +{ + CSI_PARAM_CHK_NORETVAL(pwm); + + ///< TODO:关闭输出 +} + +/** + \brief Config pwm capture mode + \param[in] pwm pwm handle to operate + \param[in] channel channel num + \param[in] polarity pwm capture polarity \ref csi_pwm_capture_polarity_t + \param[in] count pwm capture polarity count + \return error code \ref csi_error_t +*/ +csi_error_t csi_pwm_capture_config(csi_pwm_t *pwm, + uint32_t channel, + csi_pwm_capture_polarity_t polarity, + uint32_t count) +{ + CSI_PARAM_CHK(pwm, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< TODO:检查参数channel的正确性 + + if (CSI_OK == ret) { + switch (polarity) { + case PWM_CAPTURE_POLARITY_POSEDGE: + ///< TODO:设置PWM捕获的极性为posedge edge + break; + + case PWM_CAPTURE_POLARITY_NEGEDGE: + ///< TODO:设置PWM捕获的极性为negedge edge + break; + + case PWM_CAPTURE_POLARITY_BOTHEDGE: + ///< TODO:设置PWM捕获的极性为both edge + break; + + default: + ret = CSI_ERROR; + break; + } + + ///< TODO:配置捕获次数 + + ///< TODO:配置捕获模式 + + ///< TODO:启用捕获中断 + } + + return ret; +} + +/** + \brief Start pwm capture + \param[in] pwm pwm handle to operate + \param[in] channel channel num + \return error code \ref csi_error_t +*/ +csi_error_t csi_pwm_capture_start(csi_pwm_t *pwm, uint32_t channel) +{ + CSI_PARAM_CHK(pwm, CSI_ERROR); + + ///< TODO:关闭输出使能 + + ///< TODO:打开输入捕获使能 + + ///< TODO:获取捕获次数 + + return CSI_OK; +} + +/** + \brief Stop pwm capture + \param[in] pwm pwm handle to operate + \param[in] channel channel num + \return None +*/ +void csi_pwm_capture_stop(csi_pwm_t *pwm, uint32_t channel) +{ + CSI_PARAM_CHK_NORETVAL(pwm); + + ///< TODO:关闭PWM输入捕获 + ///< TODO:关闭PWM捕获中断 +} +/** + \brief Attach pwm callback + \param[in] pwm pwm handle to operate + \param[in] callback callback func + \param[in] arg user param passed to callback + \return error code \ref csi_error_t +*/ +csi_error_t csi_pwm_attach_callback(csi_pwm_t *pwm, void *callback, void *arg) +{ + CSI_PARAM_CHK(pwm, CSI_ERROR); + + pwm->callback = callback; + pwm->arg = arg; + + ///< 注册PWM的中断服务函数和使能中断控制器对应的中断 + csi_irq_attach((uint32_t)pwm->dev.irq_num, &wj_pwm_irq_handler, &pwm->dev); + csi_irq_enable((uint32_t)pwm->dev.irq_num); + + return CSI_OK; +} + +/** + \brief Detach pwm callback + \param[in] pwm pwm handle to operate + \return None +*/ +void csi_pwm_detach_callback(csi_pwm_t *pwm) +{ + CSI_PARAM_CHK_NORETVAL(pwm); + + pwm->callback = NULL; + pwm->arg = NULL; + + ///< 禁止中断控制器对应的中断,注销PWM的中断服务函数 + csi_irq_disable((uint32_t)pwm->dev.irq_num); + csi_irq_detach((uint32_t)pwm->dev.irq_num); +} + +#ifdef CONFIG_PM +csi_error_t wj_pwm_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action) +{ + CSI_PARAM_CHK(dev, CSI_ERROR); + + csi_error_t ret = CSI_OK; + csi_pm_dev_t *pm_dev = &dev->pm_dev; + + switch (action) { + case PM_DEV_SUSPEND: + ///< TODO:恢复PWM寄存器 + break; + + case PM_DEV_RESUME: + ///< TODO:保存PWM寄存器 + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +csi_error_t csi_pwm_enable_pm(csi_pwm_t *pwm) +{ + ///< TODO:注册PWM低功耗处理函数wj_pwm_pm_action +} + +void csi_pwm_disable_pm(csi_pwm_t *pwm) +{ + csi_pm_dev_unregister(&pwm->dev); +} +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/qspi.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/qspi.c new file mode 100644 index 00000000000..6f38dd93577 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/qspi.c @@ -0,0 +1,419 @@ +#include +#include +#include +#include + +#define QSPI_DEFAULT_TRANSFER_SIZE 8U + +csi_error_t csi_qspi_init(csi_qspi_t *qspi, uint32_t idx) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + ///< 获取中断号、基地址等相关信息 + if (target_get(DEV_CD_QSPI_TAG, idx, &qspi->dev) != CSI_OK) { + ret = CSI_ERROR; + } else { + qspi->state.writeable = 1U; + qspi->state.readable = 1U; + qspi->state.error = 0U; + qspi->callback = NULL; + qspi->arg = NULL; + qspi->tx_data = NULL; + qspi->rx_data = NULL; + qspi->send = NULL; + qspi->receive = NULL; + qspi->send_receive = NULL; + qspi->tx_dma = NULL; + qspi->rx_dma = NULL; + } + + return ret; +} + +void csi_qspi_uninit(csi_qspi_t *qspi) +{ + CSI_PARAM_CHK_NORETVAL(qspi); + + ///< TODO:复位QSPI所有的寄存器 + + ///< 禁止QSPI中断控制器对应的中断,注销QSPI中断服务函数 + csi_irq_disable((uint32_t)qspi->dev.irq_num); + csi_irq_detach((uint32_t)qspi->dev.irq_num); +} + +csi_error_t csi_qspi_attach_callback(csi_qspi_t *qspi, void *callback, void *arg) +{ + CSI_PARAM_CHK(qspi , CSI_ERROR); + CSI_PARAM_CHK(callback, CSI_ERROR); + + qspi->callback = callback; + qspi->arg = arg; + + ///< 注册QSPI中断服务函数,使能QSPI中断控制器对应的中断 + csi_irq_attach((uint32_t)qspi->dev.irq_num, NULL, &qspi->dev); + csi_irq_enable((uint32_t)qspi->dev.irq_num); + + return CSI_OK; +} + +void csi_qspi_detach_callback(csi_qspi_t *qspi) +{ + CSI_PARAM_CHK_NORETVAL(qspi); + + qspi->callback = NULL; + qspi->arg = NULL; + + ///< 禁止QSPI中断控制器对应的中断,注销QSPI中断服务函数 + csi_irq_disable((uint32_t)qspi->dev.irq_num); + csi_irq_detach((uint32_t)qspi->dev.irq_num); +} + +uint32_t csi_qspi_frequence(csi_qspi_t *qspi, uint32_t hz) +{ + CSI_PARAM_CHK(qspi, 0U); + CSI_PARAM_CHK(hz, 0U); + + ///< TODO:配置QSPI的频率 + ///< TODO:获取QSPI的分频到div + ///< TODO:根据QSPI的工作频率和div获取QSPI实际使用的频率到hz + + return hz; +} + +csi_error_t csi_qspi_mode(csi_qspi_t *qspi, csi_qspi_mode_t mode) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + switch (mode) { + case QSPI_CLOCK_MODE_0: + ///< TODO:配置QSPI时钟的极性和相位 + break; + + case QSPI_CLOCK_MODE_1: + ///< TODO:配置QSPI时钟的极性和相位 + break; + + case QSPI_CLOCK_MODE_2: + ///< TODO:配置QSPI时钟的极性和相位 + break; + + case QSPI_CLOCK_MODE_3: + ///< TODO:配置QSPI时钟的极性和相位 + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +void qspi_config_command(csi_qspi_t *qspi, csi_qspi_command_t *cmd) +{ + + /* configure instruction */ + if (cmd->instruction.disabled == (bool)false) { + ///< TODO:在QSPI的STIG模式下配置QSPI的命令操作码 + } + + /* configure address */ + if (cmd->address.disabled == (bool)false) { + ///< TODO:在QSPI的STIG模式下启用QSPI的命令地址 + ///< TODO:在QSPI的STIG模式下设置QSPI的命令地址字节的大小 + ///< TODO:在QSPI的STIG模式下设置QSPI的命令地址 + } + + /* configure dummy cycles */ + if (cmd->dummy_count) { + ///< TODO:在QSPI的STIG模式下设置QSPI的周期数 + } + + /* configure mode */ + if (cmd->alt.disabled == (bool)false) { + ///< TODO:在QSPI的STIG模式下使能mode bit + ///< TODO:在QSPI的STIG模式下配置QSPI的mode bits + } + + /* configure DDR */ + if (cmd->ddr_enable) { + ///< TODO:使能QSPI的DDR位 + } +} + +csi_error_t qspi_execute_stig_command(csi_qspi_t *qspi, uint32_t timeout) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + ///< TODO:设置QSPI的执行命令 + + ///< TODO:通过while循环等待QSPI进程结束处于空闲状态,超时则超时退出 + + return ret; +} + +int32_t qspi_send(csi_qspi_t *qspi, uint32_t timeout) +{ + int32_t ret = 0; + + ret = qspi_execute_stig_command(qspi, timeout); + + /* return actual send count */ + if (ret == 0) { + ret = (int32_t)qspi->tx_size; + } + + qspi->tx_size = 0U; + return ret; +} + +int32_t csi_qspi_send(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + CSI_PARAM_CHK(cmd, CSI_ERROR); + CSI_PARAM_CHK(timeout, CSI_ERROR); + + int32_t ret = CSI_OK; + + do { + if ((qspi->state.writeable == 0U) || (qspi->state.readable == 0U)) { + ret = CSI_BUSY; + break; + } + + ///< TODO:复位控制STIG生成的SPI事务的寄存器 + + qspi_config_command(qspi, cmd); + + if (size == 0U) { + + ret = qspi_execute_stig_command(qspi, timeout); + + ///< TODO:复位控制STIG生成的SPI事务的寄存器 + break; + } + + qspi->state.writeable = 0U; + qspi->tx_data = (void *)data; + qspi->tx_size = size; + ///< TODO:获取QSPI命令的地址 + + /* TODU: transfer use indirect access mode, only support STIG mode */ + if (qspi->tx_size > QSPI_DEFAULT_TRANSFER_SIZE) { + qspi->state.writeable = 1U; + ret = CSI_ERROR; + break; + } + + /* configure qspi registers */ + ///< TODO:使能QSPI写数据 + ///< TODO:配置QSPI写数据字节的大小 + ///< TODO:配置QSPI命令地址 + ///< TODO:写数据 + + qspi->state.writeable = 1U; + ret = qspi_send(qspi, timeout); + + } while (0); + + return ret; +} + + +int32_t csi_qspi_receive(csi_qspi_t *qspi, csi_qspi_command_t *cmd, void *data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + CSI_PARAM_CHK(cmd, CSI_ERROR); + CSI_PARAM_CHK(timeout, CSI_ERROR); + + uint32_t address; + int32_t ret = CSI_OK; + uint32_t count = 0U; + uint32_t current_size = 0U; + + do { + if ((qspi->state.writeable == 0U) || (qspi->state.readable == 0U)) { + ret = CSI_BUSY; + break; + } + + qspi_config_command(qspi, cmd); + + if (size == 0U) { + ret = qspi_execute_stig_command(qspi, timeout); + + ///< TODO:复位控制STIG生成的SPI事务的寄存器 + break; + } + + + qspi->rx_data = data; + qspi->rx_size = size; + qspi->state.readable = 0U; + ///< TODO:获取QSPI命令的地址到address + + /* transfer loop */ + /* TODU: transfer use indirect access mode */ + while (qspi->rx_size > 0U) { + current_size = (qspi->rx_size > QSPI_DEFAULT_TRANSFER_SIZE) ? (uint32_t) QSPI_DEFAULT_TRANSFER_SIZE : qspi->rx_size; + + /* configure qspi registers */ + ///< TODO:配置QSPI读数据字节的大小 + ///< TODO:使能QSPI读数据 + ///< TODO:配置QSPI命令地址 + ret = (int32_t)qspi_execute_stig_command(qspi, timeout); + + if (ret < 0) { + break; + } + + ///< TODO:读数据到qspi->rx_data + qspi->rx_data += current_size; + qspi->rx_size -= current_size; + count += current_size; + address += current_size; + } + + qspi->state.readable = 1U; + + ///< TODO:复位控制STIG生成的SPI事务的寄存器 + } while (0); + + /* return actual sent count if no error occur */ + if (ret >= 0) { + ret = (int32_t)count; + } + + return ret; +} + +int32_t csi_qspi_send_receive(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *tx_data, void *rx_data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + CSI_PARAM_CHK(cmd, CSI_ERROR); + CSI_PARAM_CHK(tx_data, CSI_ERROR); + CSI_PARAM_CHK(rx_data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + CSI_PARAM_CHK(timeout, CSI_ERROR); + + return 0; +} + +csi_error_t csi_qspi_send_async(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + CSI_PARAM_CHK(cmd, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + return CSI_UNSUPPORTED; +} + +csi_error_t csi_qspi_receive_async(csi_qspi_t *qspi, csi_qspi_command_t *cmd, void *data, uint32_t size) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + CSI_PARAM_CHK(cmd, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + return CSI_UNSUPPORTED; +} + +csi_error_t csi_qspi_send_receive_async(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *tx_data, void *rx_data, uint32_t size) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + CSI_PARAM_CHK(cmd, CSI_ERROR); + CSI_PARAM_CHK(tx_data, CSI_ERROR); + CSI_PARAM_CHK(rx_data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + return CSI_UNSUPPORTED; +} + +csi_error_t csi_qspi_get_state(csi_qspi_t *qspi, csi_state_t *state) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + CSI_PARAM_CHK(state, CSI_ERROR); + + *state = qspi->state; + return CSI_OK; +} + +csi_error_t csi_qspi_link_dma(csi_qspi_t *qspi, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + CSI_PARAM_CHK(tx_dma, CSI_ERROR); + CSI_PARAM_CHK(rx_dma, CSI_ERROR); + + return CSI_UNSUPPORTED; +} + +csi_error_t csi_qspi_memory_mapped(csi_qspi_t *qspi, csi_qspi_command_t *cmd) +{ + CSI_PARAM_CHK(qspi, CSI_ERROR); + CSI_PARAM_CHK(cmd, CSI_ERROR); + + ///< TODO:配置读取操作码的宽度 + + ///< TODO:配置指令类型 + + ///< TODO:配置读数据地址的宽度 + ///< TODO:配置读数据的宽度 + + ///< TODO:配置读数据的周期 + + if (cmd->alt.disabled == (bool)false) { + ///< TODO:使能读数据模式 + ///< TODO:配置QSPI模式字节的大小 + } else { + ///< TODO:禁止读数据模式 + } + + if (cmd->ddr_enable) { + ///< TODO:使能QSPI的DDR位 + } + + return CSI_OK; +} + +#ifdef CONFIG_PM +static csi_error_t dw_qspi_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action) +{ + CSI_PARAM_CHK(dev, CSI_ERROR); + + csi_error_t ret = CSI_OK; + csi_pm_dev_t *pm_dev = &dev->pm_dev; + + switch (action) { + case PM_DEV_SUSPEND: + ///< TODO:恢复QSPI寄存器 + break; + + case PM_DEV_RESUME: + ///< TODO:保存QSPI寄存器 + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +csi_error_t csi_qspi_enable_pm(csi_qspi_t *qspi) +{ + ///< TODO:注册QSPI低功耗处理函数dw_qspi_pm_action +} + +void csi_qspi_disable_pm(csi_qspi_t *qspi) +{ + csi_pm_dev_unregister(&qspi->dev); +} +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/rsa.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/rsa.c new file mode 100644 index 00000000000..8b9f6dea4bf --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/rsa.c @@ -0,0 +1,1458 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file rsa.c + * @brief CSI Source File for RSA Driver + * @version V1.0 + * @date 24. Jan 2020 + ******************************************************************************/ +#include +#include +#include +#include +#include + +#define UINT32_TO_UINT64(data) ((uint64_t)(((uint64_t)(data)) & 0x00000000ffffffffU)) +#define UINT64L_TO_UINT32(data) ((uint32_t)(((uint64_t)(data)) & 0x00000000ffffffffU)) +#define UINT64H_TO_UINT32(data) ((uint32_t)((((uint64_t)(data)) >> 32U) & 0x00000000ffffffffU)) + +#define GET_KEY_BYTE(k) (k >> 3U) +#define GET_KEY_WORD(k) (k >> 5U) + +///< TODO:RSA_KEY_LEN需要根据实际情况进行设置 +#define RSA_KEY_LEN 2048U ///< 支持RSA秘钥的最大长度 +#define RSA_KEY_BYTE (RSA_KEY_LEN >> 3U) +#define RSA_KEY_WORD (RSA_KEY_LEN >> 5U) + +#define BN_MAX_BITS ((RSA_KEY_LEN << 1U) + 32U) +#define BN_MAX_BYTES ((BN_MAX_BITS + 7U) >> 3U) +#define BN_MAX_WORDS ((BN_MAX_BYTES + 3U) >> 2U) + +///< TODO:MAX_RSA_LP_CNT需要根据实际情况进行设置 +#define MAX_RSA_LP_CNT 10000U ///< 循环计数器的最大值 + +#define PKCS1_PADDING 0x01U +#define NO_PADDING 0x02U + +#define MD5_PADDING 0x00U ///< 加密类型 +#define SHA1_PADDING 0x01U +#define SHA256_PADDING 0x03U + +#define MD5_HASH_SZ 16U ///< 加密类型对应的密文的长度 +#define SHA1_HASH_SZ 20U +#define SHA256_HASH_SZ 32U + +extern uint8_t modulus[]; +static uint32_t g_acc[RSA_KEY_WORD] = {0}; +static rsa_middle_t rsa_config_t; + +typedef struct bignum { + uint32_t pdata[BN_MAX_WORDS]; + uint32_t words; +} bignum_t; + +static void rsa_get_result(csi_rsa_t *rsa, uint8_t *result); +static void rsa_calc_rsaresult(csi_rsa_t *rsa); + +void wj_rsa_irq_handler(void *arg) +{ + csi_rsa_callback_t cb_func; + + CSI_PARAM_CHK_NORETVAL(arg); + csi_rsa_t *rsa = (csi_rsa_t *)arg; + uint32_t irq_state = 0, q_state = 0, rsa_state = 0; + + ///< TODO:获取RSA的Abnormal1、Abnormal2、Abnormal3、Abnormal4的中断状态到irq_state + if (irq_state) { + cb_func = rsa->cb; + + if (cb_func) { + cb_func(rsa, RSA_EVENT_ERROR, NULL); + } + } else { + ///< TODO:RSA的中断没有发生 + + ///< TODO:软件复位RSAte + ///< TODO:获取q计算状态 到q_state + ///< TODO:获取rsa中断状态 到rsa_state + if (q_state) { + ///< TODO:使能RSA Q计算 + ///< 计算结果 + rsa_calc_rsaresult(rsa); + } else if (rsa_state) { + uint8_t result = 0xff; + ///< TODO:清除rsa中断 + ///< 获取计算结果 + rsa_get_result(rsa, &result); + cb_func = rsa->cb; + + if (cb_func) { + if (result == 0xff) { + cb_func(rsa, RSA_EVENT_COMPLETE, NULL); + + } else { + if (result == 1) { + cb_func(rsa, RSA_EVENT_VERIFY_SUCCESS, NULL); + } else { + cb_func(rsa, RSA_EVENT_VERIFY_FAILED, NULL); + } + } + } + } + + } + +} + +/** + \brief Initialize RSA Interface. 1. Initializes the resources needed for the RSA interface 2.registers event callback function + \param[in] rsa rsa handle to operate. + \param[in] idx device id + \return \ref csi_error_t +*/ +csi_error_t csi_rsa_init(csi_rsa_t *rsa, uint32_t idx) +{ + + CSI_PARAM_CHK(rsa, CSI_ERROR); + ///< 获取中断号、基地址等相关信息 + target_get(DEV_WJ_RSA_TAG, idx, &rsa->dev); + + ///< TODO:对RSA所有的寄存器进行清零操作 + ///< TODO:清除中断 + ///< 附着中断处理函数 + csi_irq_attach(rsa->dev.irq_num, &wj_rsa_irq_handler, &rsa->dev); + ///< 开中断 + csi_irq_enable(rsa->dev.irq_num); + + return CSI_OK; +} + +/** + \brief De-initialize RSA Interface. stops operation and releases the software resources used by the interface + \param[in] rsa rsa handle to operate. + \return none +*/ +void csi_rsa_uninit(csi_rsa_t *rsa) +{ + + CSI_PARAM_CHK_NORETVAL(rsa); + + ///< TODO:清除中断 + ///< 去中断附着 + csi_irq_detach(rsa->dev.irq_num); + ///< 关中断 + csi_irq_disable(rsa->dev.irq_num); + + rsa->cb = NULL; + ///< TODO:对RSA所有的寄存器进行清零操作 + +} + +/** + \brief attach the callback handler to RSA + \param[in] rsa operate handle. + \param[in] cb callback function + \param[in] arg user can define it by himself as callback's param + \return error code +*/ +csi_error_t csi_rsa_attach_callback(csi_rsa_t *rsa, csi_rsa_callback_t cb, void *arg) +{ + CSI_PARAM_CHK(rsa, CSI_ERROR); + rsa->cb = cb; + rsa->arg = arg; + return CSI_OK; +} + +/** + \brief detach the callback handler + \param[in] rsa operate handle. +*/ +void csi_rsa_detach_callback(csi_rsa_t *rsa) +{ + CSI_PARAM_CHK_NORETVAL(rsa); + rsa->cb = NULL; +} + +static uint32_t get_valid_bits(const uint32_t *addr, uint32_t wordsize, uint32_t keywords) +{ + uint32_t i = 0; + uint32_t j = 0; + + for (i = wordsize; i > 0; i--) { + if (addr[i - 1]) { + break; + } + } + + for (j = keywords; j > 0; j--) { + if (addr[i - 1] & (0x1 << (j - 1))) { + break; + } + } + + return ((i - 1) << 5) + j; +} + +static uint32_t get_first_nonzero_words(uint32_t *a, uint32_t max_words) +{ + uint32_t i = 0; + + for (i = max_words; i > 0; i--) { + if (a[i - 1]) { + return i; + } + } + + return 0; +} + +static uint32_t word_array_left_shift(uint32_t *a, uint32_t words, + uint32_t shift_bits, uint32_t *r) +{ + uint32_t i = 0; + uint32_t w = shift_bits >> 5; + uint32_t b = shift_bits - (w << 5); + + for (i = 0; i < w; i++) { + r[i] = 0; + } + + uint32_t tmp = 0; + + for (i = 0; i < words; i++) { + r[w + i] = (tmp | ((a[i] << b) & (~((0x1 << b) - 1)))); + tmp = ((a[i] >> (32 - b)) & ((0x1 << b) - 1)); + } + + r[w + i] = tmp; + + return 0; +} + +static uint32_t _word_array_sub(uint32_t *a, uint32_t a_words, + uint32_t *b, uint32_t b_words, + uint32_t *r) +{ + uint32_t i; + uint64_t tmp = 0; + uint32_t borrow = 0; + + for (i = 0; i < b_words; i++) { + tmp = UINT32_TO_UINT64(a[i]) - UINT32_TO_UINT64(b[i]) - UINT32_TO_UINT64(borrow); + r[i] = UINT64L_TO_UINT32(tmp); + borrow = ((UINT64H_TO_UINT32(tmp) == 0) ? (0) : (0xffffffff - UINT64H_TO_UINT32(tmp) + 1)); + } + + for (i = b_words; i < a_words; i++) { + tmp = UINT32_TO_UINT64(a[i]) - UINT32_TO_UINT64(borrow); + r[i] = UINT64L_TO_UINT32(tmp); + borrow = ((UINT64H_TO_UINT32(tmp) == 0) ? (0) : (0xffffffff - UINT64H_TO_UINT32(tmp) + 1)); + } + + if (borrow) { + return -1; + } + + return 0; +} + +static void convert_byte_array(uint8_t *in, uint8_t *out, uint32_t len) +{ + uint32_t idx, round = len >> 1; + + for (idx = 0; idx < round; idx++) { + uint8_t tmp = *(in + idx); + *(out + idx) = *(in + len - 1 - idx); + *(out + len - 1 - idx) = tmp; + } + + if (len & 0x1) { + *(out + round) = *(in + round); + } +} + +static void convert_buf_to_bndata(const uint8_t *src, uint32_t src_bytes, + uint32_t *dst, uint32_t dst_words) +{ + memset(dst, 0, dst_words << 2); + convert_byte_array((uint8_t *)src, (uint8_t *)dst, src_bytes); +} + +static void convert_bndata_to_buf(const uint32_t *src, uint32_t src_words, + uint8_t *dst, uint32_t dst_bytes) +{ + memset(dst, 0, dst_bytes); + convert_byte_array((uint8_t *)src, (uint8_t *)dst, dst_bytes); +} + + +static const uint8_t der_sha256_t[] = { + 0x30, 0x31, + 0x30, 0x0d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ + 0x05, 0x00, + 0x04, 0x20 +}; + +static const uint8_t der_sha1_t[] = { + 0x30, 0x21, + 0x30, 0x09, + 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, + 0x05, 0x00, + 0x04, 0x14 +}; + +static const uint8_t der_md5_t[] = { + 0x30, 0x20, /* type Sequence, length 0x20 (32) */ + 0x30, 0x0c, /* type Sequence, length 0x09 */ + 0x06, 0x08, /* type OID, length 0x05 */ + 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */ + 0x05, 0x00, /* NULL */ + 0x04, 0x10 /* Octet string, length 0x10 (16), followed by md5 hash */ +}; +static uint32_t rsa_padding_pkcs(uint8_t *dgst, + uint8_t *out, + uint32_t type, + uint32_t keybytes) + +{ + uint32_t i; + uint8_t *p; + uint8_t *der; + uint32_t der_len; + uint32_t hashlen; + uint32_t pslen; + + if (type == MD5_PADDING) { + der = (uint8_t *)der_md5_t; + der_len = sizeof(der_md5_t); + hashlen = MD5_HASH_SZ; + } else if (type == SHA256_PADDING) { + der = (uint8_t *)der_sha256_t; + der_len = sizeof(der_sha256_t); + hashlen = SHA256_HASH_SZ; + } else { + der = (uint8_t *)der_sha1_t; + der_len = sizeof(der_sha1_t); + hashlen = SHA1_HASH_SZ; + } + + p = (uint8_t *)out; + + *(p++) = 0x00; + *(p++) = 0x01; + + /* pad out with 0xff data */ + pslen = keybytes - 3 - der_len - hashlen; + + for (i = 0; i < pslen; i++) { + p[i] = 0xff; /* PS */ + } + + p += pslen; + *(p++) = 0x0; + + for (i = 0; i < der_len; i++) { + p[i] = der[i]; + } + + p += der_len; + + for (i = 0; i < hashlen; i++) { + p[i] = dgst[i]; + } + + return 0; +} + +static uint32_t rsa_checking_pkcs(uint8_t *dgst, + uint8_t *in, + uint32_t inlen, + uint8_t *is_valid, + uint32_t type, + uint32_t keybytes) +{ + uint32_t i; + uint32_t ret; + const uint8_t *p; + uint8_t *der = (uint8_t *)der_sha1_t; + uint32_t der_len = sizeof(der_sha1_t); + uint32_t hashlen = SHA1_HASH_SZ; + uint32_t pslen; + + if (type == MD5_PADDING) { + der = (uint8_t *)der_md5_t; + der_len = sizeof(der_md5_t); + hashlen = MD5_HASH_SZ; + } else if (type == SHA1_PADDING) { + der = (uint8_t *)der_sha1_t; + der_len = sizeof(der_sha1_t); + hashlen = SHA1_HASH_SZ; + } else if (type == SHA256_PADDING) { + der = (uint8_t *)der_sha256_t; + der_len = sizeof(der_sha256_t); + hashlen = SHA256_HASH_SZ; + } + + *is_valid = 0; + + pslen = keybytes - 3 - der_len - hashlen; + p = in; + p++; + + if (*(p) != 0x01) { + ret = -1; + goto _verify_fail; + } + + p++; + + /* scan PS */ + for (i = 0; i < pslen; i++) { + if (*(p + i) != 0xff) { + ret = -2; + goto _verify_fail; + } + } + + p += pslen; + + if ((*p) != 0x00) { + ret = -1; + goto _verify_fail; + } + + p++; + + /* scan t */ + for (i = 0; i < der_len; i++) { + if (*(p + i) != der[i]) { + ret = -3; + goto _verify_fail; + } + } + + p += der_len; + + for (i = 0; i < hashlen; i++) { + if (*(p + i) != dgst[i]) { + ret = -4; + goto _verify_fail; + } + } + + *is_valid = 1; + ret = 0; + +_verify_fail: + + return ret; +} + +static uint32_t rsa_padding_es_pkcs(uint8_t *dgst, + uint32_t dgstlen, + uint8_t *out, + uint32_t padding, + uint32_t keybytes) + +{ + uint32_t i; + uint8_t *p; + uint32_t pslen; + + p = (uint8_t *)out; + + *(p++) = 0x00; + *(p++) = 0x02; + + /* pad out with 0xff data */ + pslen = keybytes - 3 - dgstlen; + + for (i = 0; i < pslen; i++) { + p[i] = 0xff; /* PS */ + } + + p += pslen; + *(p++) = 0x0; + + for (i = 0; i < dgstlen; i++) { + p[i] = dgst[i]; + } + + return 0; +} + +static uint32_t rsa_checking_es_pkcs(uint8_t *out, + uint32_t *out_size, + uint8_t *src, + uint32_t src_size, + uint32_t padding, + uint32_t keybytes) +{ + uint32_t i; + uint8_t *p; + uint8_t *p_src; + uint32_t pslen; + + p = (uint8_t *)src; + p_src = p; + *(p++) = 0x00; + + if (padding == PKCS1_PADDING) { + if (*(p++) != 0x02) { + return -1; + } + } else { + if (*(p++) != 0x01) { + return -2; + } + } + + pslen = src_size - 2; + + while (pslen--) { + if (*(p++) == 0x0) { + break; + } + } + + if (padding == PKCS1_PADDING) { + *out_size = pslen; + } else { + *out_size = keybytes; + } + + for (i = 0; i < *out_size; i++) { + if (padding == PKCS1_PADDING) { + out[i] = p[i]; + } else { + out[i] = p_src[i]; + } + } + + return 0; +} +static uint32_t word_array_mod(uint32_t *a, uint32_t a_words, + uint32_t *b, uint32_t b_words, + uint32_t *r, uint32_t keywords) +{ + uint32_t ret; + bignum_t tmpa; + bignum_t tmpb; + + memset(&tmpa, 0, sizeof(tmpa)); + memset(&tmpb, 0, sizeof(tmpa)); + + uint32_t b_valid_bits = get_valid_bits(b, b_words, keywords); + + memcpy(tmpa.pdata, a, (a_words << 2)); + + do { + uint32_t tmpa_words = get_first_nonzero_words(tmpa.pdata, a_words); + uint32_t tmpa_valid_bits = get_valid_bits(tmpa.pdata, tmpa_words, keywords); + + if (tmpa_valid_bits > b_valid_bits + 1) { + memset(tmpb.pdata, 0, (a_words << 2)); + word_array_left_shift(b, b_words, tmpa_valid_bits - b_valid_bits - 1, + tmpb.pdata); + uint32_t tmpb_words = get_first_nonzero_words(tmpb.pdata, a_words); + ret = _word_array_sub(tmpa.pdata, tmpa_words, tmpb.pdata, tmpb_words, tmpa.pdata); + } else if (tmpa_words == b_words) { + memcpy(r, tmpa.pdata, (tmpa_words << 2)); + ret = _word_array_sub(r, tmpa_words, b, b_words, tmpa.pdata); + } else { + ret = _word_array_sub(tmpa.pdata, tmpa_words, b, b_words, tmpa.pdata); + } + } while (ret == 0); + + return 0; +} + + +static uint32_t sw_exptmod_2_2m(const uint32_t *modulus, uint32_t words, uint32_t *tmp_c) +{ + bignum_t tmp; + + memset(&tmp, 0, sizeof(bignum_t)); + + uint32_t m_valid_bits = (words << 5); + + uint32_t data1 = 0x1; + word_array_left_shift(&data1, 1, (m_valid_bits << 1), tmp.pdata); + tmp.words = get_first_nonzero_words(tmp.pdata, words * 2 + 1); + + uint32_t ret = word_array_mod(tmp.pdata, tmp.words, + (uint32_t *)modulus, words, tmp_c, words); + + if (ret != 0) { + return ret; + } + + return 0; +} + +static uint32_t rsa_exptmod(csi_rsa_t *rsa, const uint32_t *modulus, const uint32_t *exponent, + const uint32_t *base, uint32_t *out, uint32_t keywords) +{ +#ifndef RSA_USING_ID2KEY + uint32_t tmp_c[RSA_KEY_WORD]; +#endif + uint32_t ret = 0; + uint32_t excep = 0U; + uint32_t lp = 0U; + + if ((NULL == exponent) || (NULL == base) || (NULL == out)) { + return 1; + } + +#ifndef RSA_USING_ID2KEY + + if (g_acc[0] != 0x0) { + memcpy(tmp_c, g_acc, sizeof(g_acc)); + } else { + ret = sw_exptmod_2_2m(modulus, keywords, tmp_c); + + if (ret != 0) { + return ret; + } + } + +#endif + + /* reset for safe */ + /// < TODO:软件复位 + + if (ret) { + return ret; + } + + ///< TODO:关闭所有中断 + ///< TODO:设置M值 + ///< TODO:设置D值 + ///< TODO:设置B值 + + /* set c */ +#ifndef RSA_USING_ID2KEY + ///< TODO :把tmp_c中的数据写到hard C中,写入的长度是keywords +#else + ///< TODO :把g_acc中的数据写到hard C中,写入的长度是keywords +#endif + + ///= MAX_RSA_LP_CNT) || excep) { + ret = 1; + } else { + ///< TODO:从存储结果的寄存器中取出数据到out,取出的长度是keywords + } + } else { + ret = 1; + } + + ///< TODO:使能RSA 软件复位 + return ret; +} + +static void rsa_calc_rsaresult(csi_rsa_t *rsa) +{ + + ///< TODO: 使能RSA + ///< TODO:开始RSA计算 + +} + +///rsa_state:<1:encrypt,2:decrypt,3:sign,4:verify +static void rsa_get_result(csi_rsa_t *rsa, uint8_t *result) +{ + + ///< TODO:从存储结果的寄存器中取出数据到rsa_config_t.pout,取出的长度是rsa_config_t.u32keywords + + ///< TODO:软件复位RSA + + switch (rsa_config_t.rsa_state) { + case 1: + convert_bndata_to_buf(rsa_config_t.pout, rsa_config_t.u32keywords, rsa_config_t.pdst, rsa_config_t.u32dst_words); + break; + + case 2: + convert_byte_array((uint8_t *)rsa_config_t.pout, (uint8_t *)rsa_config_t.pout, rsa_config_t.u32dst_words); + + rsa_checking_es_pkcs(rsa_config_t.pouts, + rsa_config_t.pout_size, + (uint8_t *)rsa_config_t.pout, + rsa_config_t.u32dst_words, + rsa_config_t.u32padding, + rsa_config_t.u32dst_words); + break; + + case 3: + convert_bndata_to_buf(rsa_config_t.pout, rsa_config_t.u32keywords, rsa_config_t.pdst, rsa_config_t.u32dst_words); + break; + + case 4: + convert_byte_array((uint8_t *)rsa_config_t.pout, (uint8_t *)rsa_config_t.pout, rsa_config_t.u32dst_words); + + rsa_checking_pkcs(rsa_config_t.pdst, + (uint8_t *)rsa_config_t.pout, + rsa_config_t.u32dst_words, + result, + rsa_config_t.u32type, + rsa_config_t.u32dst_words); + break; + } + + rsa->state.busy = 0U; + rsa_config_t.rsa_state = 0; +} + +static uint32_t rsa_exptmod_asy(csi_rsa_t *rsa, const uint32_t *modulus, const uint32_t *exponent, + const uint32_t *base, uint32_t *out, uint32_t keywords, + uint8_t *dst, uint32_t dst_words, + uint8_t *outs, uint32_t *out_size, uint32_t padding) +{ +#ifndef RSA_USING_ID2KEY + uint32_t tmp_c[RSA_KEY_WORD]; +#endif + uint32_t ret = 0; + + if ((NULL == exponent) || (NULL == base) || (NULL == out)) { + return 1; + } + +#ifndef RSA_USING_ID2KEY + + if (g_acc[0] != 0x0) { + memcpy(tmp_c, g_acc, sizeof(g_acc)); + } else { + ret = sw_exptmod_2_2m(modulus, keywords, tmp_c); + + if (ret != 0) { + return ret; + } + } + +#endif + + /* reset for safe */ + ///< TODO:软件复位RSA + + if (ret) { + return ret; + } + + ///< TODO:使能中断 + ///< TODO:设置M + ///< TODO:设置D + ///< TODO:设置B + + /* set c */ +#ifndef RSA_USING_ID2KEY + ///< TODO :把tmp_c中的数据写到hard C中,写入的长度是keywords +#else + ///< TODO :把g_acc中的数据写到hard C中,写入的长度是keywords +#endif + + + ///< TODO:使能RSA + ///< TODO:使能RSA 计算 + + rsa_config_t.pdst = dst; + rsa_config_t.pout_size = out_size; + rsa_config_t.pouts = outs; + rsa_config_t.u32keywords = keywords; + rsa_config_t.u32padding = padding; + rsa_config_t.u32dst_words = dst_words; + + return ret; + +} + +static uint32_t rsa_exptmod_asy1(csi_rsa_t *rsa, const uint32_t *modulus, const uint32_t *exponent, + const uint32_t *base, uint32_t *out, uint32_t keywords, + uint32_t dst_words, uint8_t *dst, uint32_t type) +{ +#ifndef RSA_USING_ID2KEY + uint32_t tmp_c[RSA_KEY_WORD]; +#endif + uint32_t ret = 0; + + if ((NULL == exponent) || (NULL == base) || (NULL == out)) { + return 1; + } + +#ifndef RSA_USING_ID2KEY + + if (g_acc[0] != 0x0) { + memcpy(tmp_c, g_acc, sizeof(g_acc)); + } else { + ret = sw_exptmod_2_2m(modulus, keywords, tmp_c); + + if (ret != 0) { + return ret; + } + } + +#endif + + /* reset for safe */ + ///< 软件复位RSA + + if (ret) { + return ret; + } + + ///< TODO:使能中断 + ///< TODO:设置M + ///< TODO:设置D + ///< TODO:设置B + + /* set c */ +#ifndef RSA_USING_ID2KEY + ///< TODO :把tmp_c中的数据写到hard C中,写入的长度是keywords +#else + ///< TODO :把g_acc中的数据写到hard C中,写入的长度是keywords +#endif + + ///< TODO:使能RSA + ///< TODO:使能RSA 计算 + rsa_config_t.u32dst_words = keywords; + rsa_config_t.u32dst_words = dst_words; + rsa_config_t.pdst = dst; + rsa_config_t.u32type = type; + + return ret; + +} +/** + \brief generate rsa key pair. + \param[in] rsa rsa handle to operate. + \param[out] context Pointer to the rsa context + \return \ref csi_error_t +*/ +csi_error_t csi_rsa_gen_key(csi_rsa_t *rsa, csi_rsa_context_t *context) +{ + return CSI_OK; +} + +int rsa_encrypt(csi_rsa_t *rsa, uint8_t *n, uint8_t *e, + uint8_t *src, uint32_t src_size, + uint8_t *out, + uint32_t padding, uint32_t keybits_len) +{ + uint32_t ret; + uint32_t tmp_n[RSA_KEY_WORD]; + uint32_t tmp_e[RSA_KEY_WORD]; + uint32_t tmp_in_out[RSA_KEY_WORD]; + uint32_t keywords = 0, keybytes = 0; + keywords = GET_KEY_WORD(keybits_len); + keybytes = GET_KEY_BYTE(keybits_len); + + convert_buf_to_bndata(n, keybytes, tmp_n, keywords); + convert_buf_to_bndata(e, keybytes, tmp_e, keywords); + + if (padding == PKCS1_PADDING) { + ret = rsa_padding_es_pkcs(src, + src_size, + (uint8_t *)tmp_in_out, + padding, + keybytes); + + if (ret != 0) { + return ret; + } + + convert_byte_array((uint8_t *)tmp_in_out, (uint8_t *)tmp_in_out, keybytes); + } else { + convert_byte_array((uint8_t *)src, (uint8_t *)tmp_in_out, keybytes); + } + + ret = rsa_exptmod(rsa, tmp_n, tmp_e, tmp_in_out, tmp_in_out, keywords); + + if (ret != 0) { + return ret; + } + + convert_bndata_to_buf(tmp_in_out, keywords, out, keybytes); + + return ret; +} + +int rsa_encrypt_asy(csi_rsa_t *rsa, uint8_t *n, uint8_t *e, + uint8_t *src, uint32_t src_size, + uint8_t *out, + uint32_t padding, uint32_t keybits_len) +{ + uint32_t ret; + uint32_t tmp_n[RSA_KEY_WORD]; + uint32_t tmp_e[RSA_KEY_WORD]; + uint32_t tmp_in_out[RSA_KEY_WORD]; + uint32_t keywords = 0, keybytes = 0; + keywords = GET_KEY_WORD(keybits_len); + keybytes = GET_KEY_BYTE(keybits_len); + + convert_buf_to_bndata(n, keybytes, tmp_n, keywords); + convert_buf_to_bndata(e, keybytes, tmp_e, keywords); + + if (padding == PKCS1_PADDING) { + ret = rsa_padding_es_pkcs(src, + src_size, + (uint8_t *)tmp_in_out, + padding, + keybytes); + + if (ret != 0) { + return ret; + } + + convert_byte_array((uint8_t *)tmp_in_out, (uint8_t *)tmp_in_out, keybytes); + } else { + convert_byte_array((uint8_t *)src, (uint8_t *)tmp_in_out, keybytes); + } + + ret = rsa_exptmod_asy(rsa, tmp_n, tmp_e, tmp_in_out, tmp_in_out, keywords, out, keybytes, NULL, NULL, 0); + + return ret; +} + +/** + \brief encrypt + \param[in] rsa rsa handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size the source data len + \param[out] out Pointer to the result buffer + \return \ref csi_error_t +*/ + +csi_error_t csi_rsa_encrypt(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *out) +{ + csi_error_t ret = CSI_OK; + uint32_t bit_length = 1024; + CSI_PARAM_CHK(rsa, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + CSI_PARAM_CHK(context->n, CSI_ERROR); + CSI_PARAM_CHK(context->e, CSI_ERROR); + CSI_PARAM_CHK(src, CSI_ERROR); + CSI_PARAM_CHK(out, CSI_ERROR); + + if (src_size <= 0 || (context->padding_type != RSA_PADDING_MODE_PKCS1)) { + ret = CSI_ERROR; + } else { + + rsa->state.busy = 1U; + + if (context->key_bits == RSA_KEY_BITS_2048) { + bit_length = 2048; + } + + rsa_encrypt(rsa, (uint8_t *)context->n, (uint8_t *)context->e, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)out, (uint32_t)(context->padding_type), bit_length); + rsa->state.busy = 0U; + } + + return ret; +} + +int rsa_decrypt(csi_rsa_t *rsa, uint8_t *n, uint8_t *d, + uint8_t *src, uint32_t src_size, + uint8_t *out, uint32_t *out_size, + uint32_t padding, uint32_t keybits_len) +{ + uint32_t ret; + uint32_t tmp_n[RSA_KEY_WORD]; + uint32_t tmp_d[RSA_KEY_WORD]; + uint32_t tmp_in_out[RSA_KEY_WORD]; + uint32_t keywords = 0, keybytes = 0; + + keywords = GET_KEY_WORD(keybits_len); + keybytes = GET_KEY_BYTE(keybits_len); + + convert_buf_to_bndata(n, keybytes, tmp_n, keywords); + convert_buf_to_bndata(d, keybytes, tmp_d, keywords); + convert_buf_to_bndata(src, src_size, tmp_in_out, keywords); + + ret = rsa_exptmod(rsa, tmp_n, tmp_d, tmp_in_out, tmp_in_out, keywords); + + if (ret != 0) { + return ret; + } + + convert_byte_array((uint8_t *)tmp_in_out, (uint8_t *)tmp_in_out, keybytes); + + ret = rsa_checking_es_pkcs(out, + out_size, + (uint8_t *)tmp_in_out, + keybytes, + padding, + keybytes); + + return ret; +} + +int rsa_decrypt_asy(csi_rsa_t *rsa, uint8_t *n, uint8_t *d, + uint8_t *src, uint32_t src_size, + uint8_t *out, uint32_t *out_size, + uint32_t padding, uint32_t keybits_len) +{ + uint32_t ret; + uint32_t tmp_n[RSA_KEY_WORD]; + uint32_t tmp_d[RSA_KEY_WORD]; + uint32_t tmp_in_out[RSA_KEY_WORD]; + uint32_t keywords = 0, keybytes = 0; + + keywords = GET_KEY_WORD(keybits_len); + keybytes = GET_KEY_BYTE(keybits_len); + + convert_buf_to_bndata(n, keybytes, tmp_n, keywords); + convert_buf_to_bndata(d, keybytes, tmp_d, keywords); + convert_buf_to_bndata(src, src_size, tmp_in_out, keywords); + + ret = rsa_exptmod_asy(rsa, tmp_n, tmp_d, tmp_in_out, tmp_in_out, keywords, out, keybytes, out, out_size, padding); + return ret; +} + +/** + \brief decrypt + \param[in] rsa rsa handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size the source data len + \param[out] out Pointer to the result buffer + \param[out] out_size the result size + \return \ref csi_error_t +*/ +csi_error_t csi_rsa_decrypt(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *out, uint32_t *out_size) +{ + csi_error_t ret = CSI_OK; + uint32_t bit_length = 1024; + CSI_PARAM_CHK(rsa, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + CSI_PARAM_CHK(context->n, CSI_ERROR); + CSI_PARAM_CHK(context->d, CSI_ERROR); + CSI_PARAM_CHK(src, CSI_ERROR); + CSI_PARAM_CHK(out, CSI_ERROR); + CSI_PARAM_CHK(out_size, CSI_ERROR); + + if (src_size <= 0 || (context->padding_type != RSA_PADDING_MODE_PKCS1)) { + ret = CSI_ERROR; + } else { + rsa->state.busy = 1U; + + if (context->key_bits == RSA_KEY_BITS_2048) { + bit_length = 2048; + } + + rsa_decrypt(rsa, (uint8_t *)context->n, (uint8_t *)context->d, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)out, (uint32_t *)out_size, (uint32_t)(context->padding_type), bit_length); + rsa->state.busy = 0U; + } + + return ret; +} + +int rsa_sign(csi_rsa_t *rsa, uint8_t *n, uint8_t *d, + uint8_t *src, uint32_t src_size, + uint8_t *signature, + uint32_t type, uint32_t keybits_len) +{ + uint32_t ret; + uint32_t tmp_n[RSA_KEY_WORD]; + uint32_t tmp_d[RSA_KEY_WORD]; + uint32_t tmp_in_out[RSA_KEY_WORD]; + uint32_t keywords = 0, keybytes = 0; + + keywords = GET_KEY_WORD(keybits_len); + keybytes = GET_KEY_BYTE(keybits_len); + + convert_buf_to_bndata(n, keybytes, tmp_n, keywords); + convert_buf_to_bndata(d, keybytes, tmp_d, keywords); + + ret = rsa_padding_pkcs(src, + (uint8_t *)tmp_in_out, + type, + keybytes); + + if (ret != 0) { + return ret; + } + + convert_byte_array((uint8_t *)tmp_in_out, (uint8_t *)tmp_in_out, keybytes); + + ret = rsa_exptmod(rsa, tmp_n, tmp_d, tmp_in_out, tmp_in_out, keywords); + + if (ret != 0) { + return ret; + } + + convert_bndata_to_buf(tmp_in_out, keywords, signature, keybytes); + return 0; +} + +int rsa_sign_asy(csi_rsa_t *rsa, uint8_t *n, uint8_t *d, + uint8_t *src, uint32_t src_size, + uint8_t *signature, + uint32_t type, uint32_t keybits_len) +{ + uint32_t ret; + uint32_t tmp_n[RSA_KEY_WORD]; + uint32_t tmp_d[RSA_KEY_WORD]; + uint32_t tmp_in_out[RSA_KEY_WORD]; + uint32_t keywords = 0, keybytes = 0; + + keywords = GET_KEY_WORD(keybits_len); + keybytes = GET_KEY_BYTE(keybits_len); + + convert_buf_to_bndata(n, keybytes, tmp_n, keywords); + convert_buf_to_bndata(d, keybytes, tmp_d, keywords); + + ret = rsa_padding_pkcs(src, + (uint8_t *)tmp_in_out, + type, + keybytes); + + if (ret != 0) { + return ret; + } + + convert_byte_array((uint8_t *)tmp_in_out, (uint8_t *)tmp_in_out, keybytes); + ret = rsa_exptmod_asy(rsa, tmp_n, tmp_d, tmp_in_out, tmp_in_out, keywords, signature, keybytes, NULL, NULL, 0); + return 0; +} + +/** + \brief rsa sign + \param[in] rsa rsa handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size the source data len + \param[out] signature Pointer to the signature + \param[in] hash_type the source data hash type + \return \ref csi_error_t +*/ +csi_error_t csi_rsa_sign(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *signature, csi_rsa_hash_type_t hash_type) +{ + csi_error_t ret = CSI_OK; + uint32_t bit_length = 1024; + CSI_PARAM_CHK(rsa, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + CSI_PARAM_CHK(context->n, CSI_ERROR); + CSI_PARAM_CHK(context->d, CSI_ERROR); + CSI_PARAM_CHK(src, CSI_ERROR); + CSI_PARAM_CHK(signature, CSI_ERROR); + + if (src_size <= 0 || (hash_type != RSA_HASH_TYPE_MD5 + && hash_type != RSA_HASH_TYPE_SHA1 + && hash_type != RSA_HASH_TYPE_SHA256)) { + ret = CSI_ERROR; + } else { + rsa->state.busy = 1U; + + if (context->key_bits == RSA_KEY_BITS_2048) { + bit_length = 2048; + } + + rsa_sign(rsa, (uint8_t *)context->n, (uint8_t *)context->d, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)signature, (uint32_t)(hash_type), bit_length); + rsa->state.busy = 0U; + } + + return ret; +} + +int rsa_verify(csi_rsa_t *rsa, uint8_t *n, uint8_t *e, + uint8_t *src, uint32_t src_size, + uint8_t *signature, uint32_t sig_size, + uint32_t type, uint32_t keybits_len, + uint8_t *result) +{ + uint32_t ret; + uint32_t tmp_n[RSA_KEY_WORD]; + uint32_t tmp_e[RSA_KEY_WORD]; + uint32_t tmp_in_out[RSA_KEY_WORD]; + uint32_t keywords = 0, keybytes = 0; + + *result = 0; + + keywords = GET_KEY_WORD(keybits_len); + keybytes = GET_KEY_BYTE(keybits_len); + + convert_buf_to_bndata(n, keybytes, tmp_n, keywords); + convert_buf_to_bndata(e, keybytes, tmp_e, keywords); + convert_buf_to_bndata(signature, sig_size, tmp_in_out, keywords); + + ret = rsa_exptmod(rsa, tmp_n, tmp_e, tmp_in_out, tmp_in_out, keywords); + + if (ret != 0) { + return ret; + } + + convert_byte_array((uint8_t *)tmp_in_out, (uint8_t *)tmp_in_out, keybytes); + + ret = rsa_checking_pkcs(src, + (uint8_t *)tmp_in_out, + keybytes, + result, + type, + keybytes); + + return ret; +} + +int rsa_verify_asy(csi_rsa_t *rsa, uint8_t *n, uint8_t *e, + uint8_t *src, uint32_t src_size, + uint8_t *signature, uint32_t sig_size, + uint32_t type, uint32_t keybits_len) +{ + uint32_t ret; + uint32_t tmp_n[RSA_KEY_WORD]; + uint32_t tmp_e[RSA_KEY_WORD]; + uint32_t tmp_in_out[RSA_KEY_WORD]; + uint32_t keywords = 0, keybytes = 0; + + + + keywords = GET_KEY_WORD(keybits_len); + keybytes = GET_KEY_BYTE(keybits_len); + + convert_buf_to_bndata(n, keybytes, tmp_n, keywords); + convert_buf_to_bndata(e, keybytes, tmp_e, keywords); + convert_buf_to_bndata(signature, sig_size, tmp_in_out, keywords); + + ret = rsa_exptmod_asy1(rsa, tmp_n, tmp_e, tmp_in_out, tmp_in_out, keywords, keybytes, src, type); + return ret; +} +/** + \brief rsa verify + \param[in] rsa rsa handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size the source data len + \param[in] signature Pointer to the signature + \param[in] sig_size the signature size + \param[in] hash_type the source data hash type + \return verify result +*/ +bool csi_rsa_verify(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *signature, uint32_t sig_size, csi_rsa_hash_type_t hash_type) +{ + // csi_rsa_callback_t cb_func; + bool result; + CSI_PARAM_CHK(rsa, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + CSI_PARAM_CHK(context->n, CSI_ERROR); + CSI_PARAM_CHK(context->e, CSI_ERROR); + CSI_PARAM_CHK(src, CSI_ERROR); + CSI_PARAM_CHK(signature, CSI_ERROR); + + + if (src_size <= 0 || sig_size <= 0 || (context->padding_type != RSA_PADDING_MODE_PKCS1)) { + result = false; + } else { + + rsa->state.busy = 1U; + + uint32_t bit_length = 1024; + + if (context->key_bits == RSA_KEY_BITS_2048) { + bit_length = 2048; + } + + rsa_verify(rsa, (uint8_t *)context->n, (uint8_t *)context->e, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)signature, sig_size, (uint32_t)(context->padding_type), bit_length, (uint8_t *)&result); + rsa->state.busy = 0U; + } + + return result; +} + +/** + \brief encrypt(async mode) + \param[in] rsa rsa handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size the source data len + \param[out] out Pointer to the result buffer + \return \ref csi_error_t +*/ +csi_error_t csi_rsa_encrypt_async(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *out) +{ + csi_error_t ret = CSI_OK; + uint32_t bit_length = 1024; + + CSI_PARAM_CHK(rsa, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + CSI_PARAM_CHK(context->n, CSI_ERROR); + CSI_PARAM_CHK(context->e, CSI_ERROR); + CSI_PARAM_CHK(src, CSI_ERROR); + CSI_PARAM_CHK(out, CSI_ERROR); + + if (src_size <= 0 || (context->padding_type != RSA_PADDING_MODE_PKCS1)) { + ret = CSI_ERROR; + } else { + + rsa->state.busy = 1U; + + if (context->key_bits == RSA_KEY_BITS_2048) { + bit_length = 2048; + } + + rsa_config_t.rsa_state = 1; + rsa_encrypt_asy(rsa, (uint8_t *)context->n, (uint8_t *)context->e, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)out, (uint32_t)(context->padding_type), bit_length); + } + + return ret; +} + +/** + \brief decrypt(async mode) + \param[in] rsa rsa handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size the source data len + \param[out] out Pointer to the result buffer + \param[out] out_size the result size + \return \ref csi_error_t +*/ +csi_error_t csi_rsa_decrypt_async(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *out, uint32_t *out_size) +{ + csi_error_t ret = CSI_OK; + uint32_t bit_length = 1024; + CSI_PARAM_CHK(rsa, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + CSI_PARAM_CHK(context->n, CSI_ERROR); + CSI_PARAM_CHK(context->d, CSI_ERROR); + CSI_PARAM_CHK(src, CSI_ERROR); + CSI_PARAM_CHK(out, CSI_ERROR); + CSI_PARAM_CHK(out_size, CSI_ERROR); + + if (src_size <= 0 || (context->padding_type != RSA_PADDING_MODE_PKCS1)) { + ret = CSI_ERROR; + } else { + rsa->state.busy = 1U; + + if (context->key_bits == RSA_KEY_BITS_2048) { + bit_length = 2048; + } + + rsa_config_t.rsa_state = 2; + rsa_decrypt_asy(rsa, (uint8_t *)context->n, (uint8_t *)context->d, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)out, (uint32_t *)out_size, (uint32_t)(context->padding_type), bit_length); + } + + return ret; +} + +/** + \brief rsa sign(async mode) + \param[in] rsa rsa handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size the source data len + \param[out] signature Pointer to the signature + \param[in] hash_type the source data hash type + \return \ref csi_error_t +*/ +csi_error_t csi_rsa_sign_async(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *signature, csi_rsa_hash_type_t hash_type) +{ + csi_error_t ret = CSI_OK; + uint32_t bit_length = 1024; + CSI_PARAM_CHK(rsa, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + CSI_PARAM_CHK(context->n, CSI_ERROR); + CSI_PARAM_CHK(context->d, CSI_ERROR); + CSI_PARAM_CHK(src, CSI_ERROR); + CSI_PARAM_CHK(signature, CSI_ERROR); + + if (src_size <= 0 || (hash_type != RSA_HASH_TYPE_MD5 + && hash_type != RSA_HASH_TYPE_SHA1 + && hash_type != RSA_HASH_TYPE_SHA256)) { + ret = CSI_ERROR; + } else { + rsa->state.busy = 1U; + + if (context->key_bits == RSA_KEY_BITS_2048) { + bit_length = 2048; + } + + rsa_config_t.rsa_state = 3; + rsa_sign_asy(rsa, (uint8_t *)context->n, (uint8_t *)context->d, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)signature, (uint32_t)(hash_type), bit_length); + } + + return ret; +} + +/** + \brief rsa verify(async mode) + \param[in] rsa rsa handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size the source data len + \param[in] signature Pointer to the signature + \param[in] sig_size the signature size + \param[in] hash_type the source data hash type + \return verify result +*/ +csi_error_t csi_rsa_verify_async(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *signature, uint32_t sig_size, csi_rsa_hash_type_t hash_type) +{ + CSI_PARAM_CHK(rsa, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + CSI_PARAM_CHK(context->n, CSI_ERROR); + CSI_PARAM_CHK(context->e, CSI_ERROR); + CSI_PARAM_CHK(src, CSI_ERROR); + CSI_PARAM_CHK(signature, CSI_ERROR); + + + if (src_size <= 0 || sig_size <= 0 || (context->padding_type != RSA_PADDING_MODE_PKCS1)) { + } else { + + rsa->state.busy = 1U; + + uint32_t bit_length = 1024; + + if (context->key_bits == RSA_KEY_BITS_2048) { + bit_length = 2048; + } + + rsa_config_t.rsa_state = 4; + rsa_verify_asy(rsa, (uint8_t *)context->n, (uint8_t *)context->e, (uint8_t *)src, (uint32_t)src_size, (uint8_t *)signature, sig_size, (uint32_t)(context->padding_type), bit_length); + } + + return CSI_OK; +} + +/** + \brief Get RSA state. + \param[in] rsa rsa handle to operate. + \param[out] state rsa state \ref csi_rsa_state_t. + \return \ref csi_error_t +*/ +csi_error_t csi_rsa_get_state(csi_rsa_t *rsa, csi_rsa_state_t *state) +{ + CSI_PARAM_CHK(rsa, CSI_ERROR); + *state = rsa->state; + return CSI_OK; +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/rtc.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/rtc.c new file mode 100644 index 00000000000..f3f7083447f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/rtc.c @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + */ + +/******************************************************* + * @file rtc.c + * @brief source file for rtc csi driver + * @version V1.0 + * @date 23. Sep 2020 + * ******************************************************/ + +#include +#include +#include + +#define NORMAL_RTC_FREQ (32768U) +#define REAL_RTC_FREQ (soc_get_rtc_freq(0U)) +#define RTC_WAIT_WRITED_10S (10000U) + +#define RTC_WAIT_IS_TIMEOUT(_time_ms_, _result_) { \ + do { \ + if (_time_ms_ >= RTC_WAIT_WRITED_10S) { \ + _result_ = -1; \ + } \ + mdelay(1U); \ + } while(0); \ + } + +static uint32_t load_time = 0U; +static uint32_t int_number = 0U; +static uint32_t count = 0U; + +extern int32_t clock_check_tm_ok(const struct tm *rtctime); +extern int32_t clock_update_basetime(const struct tm *rtctime); +extern time_t mktime(struct tm *tp); + +/** + \brief Internal timeout interrupt process function + \param[in] rtc handle rtc handle to operate + \return None +*/ +void qx_rtc_irq_handler(void *arg) +{ + csi_rtc_t *rtc = (csi_rtc_t *)arg; + uint32_t timecount = 0, ret = 0, intr_status = 0; + + ///< TODO:获取RTC中断的状态到intr_status + + do { + ///< TODO:清除RTC的中断 + RTC_WAIT_IS_TIMEOUT(++timecount, ret); + + if (ret < 0) { + break; + } + } while (intr_status); + + count++; + + if (count >= (int_number * (REAL_RTC_FREQ / NORMAL_RTC_FREQ))) { + count = 0U; + + if (rtc->callback) { + rtc->callback(rtc, rtc->arg); + } + } + +} +/** + \brief Initialize RTC Interface. Initializes the resources needed for the RTC interface + \param[in] rtc rtc handle to operate + \param[in] idx rtc index + \return error code \ref csi_error_t +*/ +csi_error_t csi_rtc_init(csi_rtc_t *rtc, uint32_t idx) +{ + CSI_PARAM_CHK(rtc, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< 获取中断号、基地址等相关信息 + if (0 == target_get(DEV_QX_RTC_TAG, idx, &rtc->dev)) { + ///< TODO:相关寄存器复位清零 + } else { + ret = CSI_ERROR; + } + + return ret; +} +/** + \brief De-initialize RTC Interface. stops operation and releases the software resources used by the interface + \param[in] rtc rtc handle to operate + \return None +*/ +void csi_rtc_uninit(csi_rtc_t *rtc) +{ + CSI_PARAM_CHK_NORETVAL(rtc); + + ///< TODO:相关寄存器复位清零 +} + +/** + \brief Set system date + \param[in] rtc handle rtc handle to operate + \param[in] rtctime pointer to rtc time + \return error code \ref csi_error_t +*/ +csi_error_t csi_rtc_set_time(csi_rtc_t *rtc, const csi_rtc_time_t *rtctime) +{ + CSI_PARAM_CHK(rtc, CSI_ERROR); + CSI_PARAM_CHK(rtctime, CSI_ERROR); + csi_error_t ret = CSI_OK; + int32_t load_sec; + + do { + ret = (csi_error_t)clock_check_tm_ok((const struct tm *)rtctime); + + if (ret < CSI_OK) { + break; + } + + load_sec = clock_update_basetime((const struct tm *)rtctime); + + if (load_sec <= 0) { ///< Error returned when total seconds overflow is negative + ret = CSI_ERROR; + break; + } + + load_time = (uint32_t)load_sec; + ///< TODO:用load_sec设置RTC的加载值寄存器,该处操作有一段等待同步时间 + + if (ret < CSI_OK) { + break; + } + + ///< TODO:使能计数器 + + } while (0); + + return ret; +} +/** + \brief Set system date but no wait + \param[in] rtc rtc handle to operate + \param[in] rtctime pointer to rtc time + \return error code \ref csi_error_t +*/ +csi_error_t csi_rtc_set_time_no_wait(csi_rtc_t *rtc, const csi_rtc_time_t *rtctime) +{ + CSI_PARAM_CHK(rtc, CSI_ERROR); + CSI_PARAM_CHK(rtctime, CSI_ERROR); + csi_error_t ret = CSI_OK; + int32_t load_sec; + + do { + + ret = (csi_error_t)clock_check_tm_ok((const struct tm *)rtctime); + + if (ret < CSI_OK) { + break; + } + + load_sec = clock_update_basetime((const struct tm *)rtctime); + + if (load_sec <= 0) { ///< Error returned when total seconds overflow is negative + ret = CSI_ERROR; + break; + } + + ///< TODO:用load_sec设置RTC的加载值寄存器 + + ///< TODO:使能计数器 + + } while (0); + + return ret; +} +/** + \brief Get system date + \param[in] rtc handle rtc handle to operate + \param[out] rtctime pointer to rtc time + \return error code \ref csi_error_t +*/ +csi_error_t csi_rtc_get_time(csi_rtc_t *rtc, csi_rtc_time_t *rtctime) +{ + uint32_t cur_time = 0; + time_t time; + + CSI_PARAM_CHK(rtc, CSI_ERROR); + CSI_PARAM_CHK(rtctime, CSI_ERROR); + + ///< TODO:获取当前时间到cur_time + time = (time_t)(((cur_time - load_time) / (REAL_RTC_FREQ / NORMAL_RTC_FREQ)) + load_time); + gmtime_r(&time, (struct tm *)rtctime); + + return CSI_OK; +} + +/** + \brief Get alarm remaining time + \param[in] rtc rtc handle to operate + \return the remaining time(s) +*/ +uint32_t csi_rtc_get_alarm_remaining_time(csi_rtc_t *rtc) +{ + CSI_PARAM_CHK(rtc, 0U); + + ///< 返回RTC剩余多长时间产生闹钟中断 + return (int_number - (count / (REAL_RTC_FREQ / NORMAL_RTC_FREQ))); +} + +/** + \brief Config RTC alarm ture timer + \param[in] rtc handle rtc handle to operate + \param[in] rtctime time(s) to wake up + \param[in] callback callback function + \param[in] arg callback's param + \return error code \ref csi_error_t +*/ +csi_error_t csi_rtc_set_alarm(csi_rtc_t *rtc, const csi_rtc_time_t *rtctime, void *callback, void *arg) +{ + CSI_PARAM_CHK(rtc, CSI_ERROR); + CSI_PARAM_CHK(rtctime, CSI_ERROR); + csi_error_t ret = (csi_error_t)clock_check_tm_ok((const struct tm *)rtctime); + csi_rtc_time_t current_time; + + if (CSI_OK == ret) { + rtc->callback = callback; + rtc->arg = arg; + ///< 注册RTC的中断服务函数,使能中断控制器中对应的中断 + csi_irq_attach((uint32_t)rtc->dev.irq_num, &qx_rtc_irq_handler, &rtc->dev); + csi_irq_enable((uint32_t)rtc->dev.irq_num); + + csi_rtc_get_time(rtc, ¤t_time); ///< get current time + count = 0U; + int_number = ((uint32_t)mktime((struct tm *)rtctime) - (uint32_t)mktime((struct tm *)¤t_time)); + ///< TODO:使能RTC的中断 + } + + return ret; +} + +/** + \brief Cancel the rtc alarm + \param[in] rtc rtc handle to operate + \return error code \ref csi_error_t +*/ +csi_error_t csi_rtc_cancel_alarm(csi_rtc_t *rtc) +{ + CSI_PARAM_CHK(rtc, CSI_ERROR); + + rtc->callback = NULL; + rtc->arg = NULL; + + ///< TODO:禁止中断 + + ///< 关闭中断控制器中对应的使能,注销RTC的中断服务函数 + csi_irq_disable((uint32_t)rtc->dev.irq_num); + csi_irq_detach((uint32_t)rtc->dev.irq_num); + + return CSI_OK; +} + +/** + \brief Judge rtc is working + \param[in] rtc handle rtc handle to operate + \return state of work + ture - rtc is running + false -rtc is not running +*/ +bool csi_rtc_is_running(csi_rtc_t *rtc) +{ + CSI_PARAM_CHK(rtc, false); + + bool status = 0; + + ///< TODO:获取RTC运行的状态 + + return status; +} + +#ifdef CONFIG_PM +csi_error_t csi_rtc_enable_pm(csi_rtc_t *rtc) +{ + return CSI_UNSUPPORTED; +} + +void csi_rtc_disable_pm(csi_rtc_t *rtc) +{ + return; +} +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/sha.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/sha.c new file mode 100644 index 00000000000..d443096e8d1 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/sha.c @@ -0,0 +1,490 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + */ + +/******************************************************* + * @file wj_sha.c + * @brief source file for sha csi driver + * @version V2.0 + * @date 14. Sept 2020 + * ******************************************************/ + +#include +#include + +/** + * Different modes get different plaintext blocks + */ +#define SHA_GET_BOLOCK_SIZE_BYTES(_mod_) (((_mod_) < SHA_MODE_512) ? (uint32_t)64 : (uint32_t)128) + +/** + * Different modes get different data lengths + * \note SHA-1\SHA-224\SHA-256 need 2 * 4 = 8 bytes + * SHA-512\SHA-384 need 4 * 4 = 16 bytes + */ +#define SHA_GET_MSGLEN_TAIL_4BYTES(_mod_) (((_mod_) < SHA_MODE_512) ? (uint32_t)2 : (uint32_t)4) + +/** + * Number of result message digest bytes retrieved by sha mode + */ +#define SHA_GET_MSGDIGEST_BYTES(_mod_) (((_mod_) == SHA_MODE_1 ) ? (uint32_t)20 : \ + ((_mod_) == SHA_MODE_256) ? (uint32_t)32 : \ + ((_mod_) == SHA_MODE_224) ? (uint32_t)28 : \ + ((_mod_) == SHA_MODE_512) ? (uint32_t)64 : \ + ((_mod_) == SHA_MODE_384) ? (uint32_t)48 : \ + (uint32_t)20) + +#define SHA_ALG_ALIGN_SORT(_idx_) (_idx_ % 2U ? ((_idx_ - 1U) >> 1) : ((_idx_ >> 1) + 8U)) + +#define SHA_ALG_SWAP(_x_, _y_) { \ + uint8_t z = (uint8_t)*_x_; \ + *_x_ = (uint8_t)*_y_; \ + *_y_ = z; \ + } + +#define SHA_ALG_ALIGN_4BYTE(_len_) (((_len_) % 4U) ? ((((_len_) >> 2U) << 2U) + 4U) : (_len_)) + + +#define SHA_ALG_SELECT_MIN(_x_, _y_) (((_x_) < (_y_)) ? (_x_) : (_y_)) + +#define SHA_WAIT_WRITED_10S (10000U) + +#define SHA_WAIT_IS_TIMEOUT(_time_ms_, _result_) { \ + do { \ + if (_time_ms_ >= SHA_WAIT_WRITED_10S) { \ + _result_ = -1; \ + } \ + } while(0); \ + } + +/*> BYTE3 + SHA_ALG_SWAP((p + 1U), (p + 2U)); ///< BYTE1 <<---SWAP--->> BYTE2 + + wj_sha_alg_reverse((p + 4U), (n - 1U)); ///< offset next address(uint32_t) and reduce operate data count + } +} + +/** + \brief SHA interrupt handling function + \param[in] arg Callback function member variables + \return null +*/ +void wj_sha_irq_handler(void *arg) +{ + csi_sha_t *sha = (csi_sha_t *)arg; + uint32_t sha_irq_state = 0U; + ///< TODO:获取中断状态到sha_irq_state + if (sha_irq_state) { + if (sha->callback) { + sha->callback(sha, SHA_EVENT_COMPLETE, sha->arg); + } + + ///< TODO:清除SHA 中断状态 + } +} + +/** + \brief update the engine + \param[in] sha sha handle to operate. + \param[in] context Pointer to the sha context + \param[in] input Pointer to the Source data + \param[in] size the data size + \return \ref csi_error_t +*/ +csi_error_t wj_sha_update_sub(csi_sha_t *sha, csi_sha_context_t *context, const void *input, uint32_t size) +{ + CSI_PARAM_CHK(sha, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + csi_error_t ret = CSI_OK; + + uint8_t *p_data_in = (uint8_t *)input; + + sha->state.busy = 1U; + + *(p_data_in + size) = 0x80U; + + ///< TODO:写入计算值 + + ///< TODO:开始SHA计算 + + mdelay(1U); ///state.busy = 0U; + + return ret; +} + +/*dev)) { + + ///< TODO:清除SHA所有的寄存器 + + sha->state.busy = 0U; + } else { + ret = CSI_ERROR; + } + + return ret; +} + +/** + \brief De-initialize SHA Interface. stops operation and releases the software resources used by the interface + \param[in] sha sha handle to operate. + \return none +*/ +void csi_sha_uninit(csi_sha_t *sha) +{ + CSI_PARAM_CHK_NORETVAL(sha); + + ///< TODO:清除SHA所有的寄存器 +} + +/** + \brief attach the callback handler to SHA + \param[in] sha operate handle. + \param[in] callback callback function + \param[in] arg callback's param + \return error code +*/ +csi_error_t csi_sha_attach_callback(csi_sha_t *sha, void *callback, void *arg) +{ + CSI_PARAM_CHK(sha, CSI_ERROR); + + sha->callback = callback; + sha->arg = arg; + ///< 附着中断处理函数 + csi_irq_attach((uint32_t)sha->dev.irq_num, &wj_sha_irq_handler, &sha->dev); + ///< 使能SHA中断 + csi_irq_enable((uint32_t)sha->dev.irq_num); + + return CSI_OK; +} + +/** + \brief detach the callback handler + \param[in] sha operate handle. +*/ +void csi_sha_detach_callback(csi_sha_t *sha) +{ + CSI_PARAM_CHK_NORETVAL(sha); + sha->callback = NULL; + sha->arg = NULL; + ///< 关闭SHA 中断功能 + csi_irq_disable((uint32_t)sha->dev.irq_num); + ///< 清除SHA中断附着 + csi_irq_detach((uint32_t)sha->dev.irq_num); +} + +/** + \brief config sha mode. + \param[in] sha sha handle to operate. + \param[in] context Pointer to the sha context + \param[in] mode sha mode \ref csi_sha_mode_t + \return \ref csi_error_t +*/ +csi_error_t csi_sha_start(csi_sha_t *sha, csi_sha_context_t *context, csi_sha_mode_t mode) +{ + CSI_PARAM_CHK(sha, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + csi_error_t ret = CSI_OK; + + switch (mode) { + case SHA_MODE_1: + case SHA_MODE_256: + case SHA_MODE_224: + case SHA_MODE_512: + case SHA_MODE_384: + ///< TODO:设置SHA 模式 + ///< TODO:清除 SHA HASH 值 + ///< TODO:清除 SHA DATA 值 + + memset((void *)&context->mode, 0, sizeof(csi_sha_context_t)); + context->mode = mode; + ///< TODO:SHA 使能中断 + ///< TODO:SHA 使能初始值 + + ///< TODO:把SHA存储密文的寄存器中的内容复制sizeof(context->state)大小到context->state + break; + + case SHA_MODE_512_256: + case SHA_MODE_512_224: + ret = CSI_UNSUPPORTED; + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +/** + \brief update the engine + \param[in] sha sha handle to operate. + \param[in] context Pointer to the sha context + \param[in] input Pointer to the Source data + \param[in] size the data size + \return \ref csi_error_t +*/ +csi_error_t csi_sha_update(csi_sha_t *sha, csi_sha_context_t *context, const void *input, uint32_t size) +{ + CSI_PARAM_CHK(sha, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + csi_error_t ret = CSI_OK; + + uint8_t *p_data_in = (uint8_t *)input; + uint32_t block_size; + uint32_t timecount = 0U; + uint32_t left; + uint32_t length; + + sha->state.busy = 1U; + + ///< TODO:设置SHA 模式 + ///< TODO:用context->state初始化HASH + + block_size = SHA_GET_BOLOCK_SIZE_BYTES(context->mode); + + context->total[0] += size; + left = strlen((const char *)context->buffer); ///< Get unused message + + /** + * If there is any unused message, it will be added to the new message for calculation + */ + if (left) { + memcpy((uint8_t *)context->buffer + left, p_data_in, SHA_ALG_SELECT_MIN(block_size - left, size)); ///< pad input message to complete block + size += left; ///< input message size need add original message size(only unused) + } else { + memcpy((uint8_t *)context->buffer, p_data_in, SHA_ALG_SELECT_MIN(block_size, size)); + } + + length = size; ///< message size + + if (length >= block_size) { ///< if length > block size, need accumulate two times least + + do { + ///< TODO:写入待计算值 context->buffer + + ///< TODO:开始SHA 计算 + + mdelay(1U); ///buffer, p_data_in, block_size); + + SHA_WAIT_IS_TIMEOUT(++timecount, ret); + + if (ret != CSI_OK) { + break; + } + } while (length >= block_size); + + memset((uint8_t *)context->buffer, 0, block_size); + + memcpy((uint8_t *)context->buffer, p_data_in, (size & (block_size - 1U))); + + } + + ///< TODO:获取HASH用context->state + + sha->state.busy = 0U; + + return ret; +} + +/** + \brief accumulate the engine (async mode) + \param[in] sha sha handle to operate. + \param[in] context Pointer to the sha context + \param[in] input Pointer to the Source data + \param[in] size the data size + \return \ref csi_error_t +*/ +csi_error_t csi_sha_update_async(csi_sha_t *sha, csi_sha_context_t *context, const void *input, uint32_t size) +{ + CSI_PARAM_CHK(sha, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + + csi_error_t ret = CSI_UNSUPPORTED; + + return ret; +} + +/** + \brief finish the engine + \param[in] sha sha handle to operate. + \param[in] context Pointer to the sha context + \param[out] output Pointer to the result data + \param[out] out_size Pointer to the result data size(bytes) + \return \ref csi_error_t +*/ +csi_error_t csi_sha_finish(csi_sha_t *sha, csi_sha_context_t *context, void *output, uint32_t *out_size) +{ + CSI_PARAM_CHK(sha, CSI_ERROR); + CSI_PARAM_CHK(context, CSI_ERROR); + csi_error_t ret = CSI_OK; + + uint32_t *p_data_in = (uint32_t *)context->buffer; + uint8_t *out_buf = (uint8_t *)output; + uint32_t i; + uint32_t msg_length; + uint32_t block_size; + uint32_t length; + uint32_t size = context->total[0]; + uint32_t pad_buf[4] = {0U}; + uint64_t pad_bit_len; + + ///< TODO:设置SHA 模式 + ///< TODO:用context->state初始化HASH + + block_size = SHA_GET_BOLOCK_SIZE_BYTES(context->mode); + msg_length = SHA_GET_MSGLEN_TAIL_4BYTES(context->mode); + + pad_bit_len = (uint64_t)size << 3U; ///< write message length into memory behind message + + length = (strlen((char *)context->buffer) + (msg_length << 2U)) + 1U; ///< message size + extra length + format(0x80) + + if (length > block_size) { + wj_sha_update_sub(sha, context, p_data_in, size); + memset((uint8_t *)context->buffer, 0, sizeof(context->buffer)); + } else { + pad_buf[0] = 0x80U; + memcpy((uint8_t *)p_data_in + (size % block_size), &pad_buf[0], sizeof(uint32_t)); ///< add tail(msg bit length) + } + + pad_buf[1] = (uint32_t)pad_bit_len >> 16; + pad_buf[2] = (uint32_t)pad_bit_len; + wj_sha_alg_reverse((uint8_t *)&pad_buf[1], 2U); + + memcpy((uint8_t *)p_data_in + block_size - 8U, &pad_buf[1], sizeof(uint32_t) << 1); ///< add tail(msg bit length) + + ///< TODO:写入待计算值 p_data_in + + ///< TODO:开始SHA计算 + + mdelay(1U); ///mode); + + if (*out_size < SHA_GET_MSGDIGEST_BYTES(SHA_MODE_384)) { + ///< TODO:把SHA存储密文的寄存器中的内容复制out_size大小到context->buffer + wj_sha_alg_reverse(context->buffer, ((uint8_t)*out_size) >> 2U); ///< Flip the last result data + memcpy(out_buf, context->buffer, *out_size); + } else { + ///< TODO:把SHA存储密文的寄存器中的内容复制64大小到context->buffer + wj_sha_alg_reverse(context->buffer, 16U); ///< Flip the last result data + + for (i = 0U; i < (*out_size >> 2); i++) { + wj_sha_alg_sort(out_buf, context->buffer + (SHA_ALG_ALIGN_SORT(i) << 2), i); + } + } + + ///< TODO:开始SHA HASH + ///< TODO:开始SHA DATA + + /** + * clean cache + */ + memset((uint8_t *)context->total, 0, sizeof(context->total)); + memset((uint8_t *)context->state, 0, sizeof(context->state)); + memset((uint8_t *)context->buffer, 0, sizeof(context->buffer)); + + return ret; +} + +/** + \brief Get SHA state. + \param[in] sha sha handle to operate. + \param[out] state sha state \ref csi_sha_state_t. + \return \ref csi_error_t +*/ +csi_error_t csi_sha_get_state(csi_sha_t *sha, csi_sha_state_t *state) +{ + CSI_PARAM_CHK(sha, CSI_ERROR); + CSI_PARAM_CHK(state, CSI_ERROR); + + state->busy = sha->state.busy; + state->error = sha->state.error; + + return CSI_OK; +} + +#ifdef CONFIG_PM +csi_error_t wj_sha_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action) +{ + CSI_PARAM_CHK(dev, CSI_ERROR); + + csi_error_t ret = CSI_OK; + csi_pm_dev_t *pm_dev = &dev->pm_dev; + + switch (action) { + case PM_DEV_SUSPEND: + ///< TODO:恢复SHA 寄存器 + break; + + case PM_DEV_RESUME: + ///< TODO:保存SHA 寄存器 + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +csi_error_t csi_sha_enable_pm(csi_sha_t *sha) +{ + ///< TODO:注册 SHA 低功耗处理函数 + return csi_pm_dev_register(&sha->dev, wj_sha_pm_action, 25U, 0U); +} + +void csi_sha_disable_pm(csi_sha_t *sha) +{ + csi_pm_dev_unregister(&sha->dev); +} +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/spi.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/spi.c new file mode 100644 index 00000000000..5cd7eb60ece --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/spi.c @@ -0,0 +1,754 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file dw_spi.c + * @brief + * @version + * @date 2020-02-11 + ******************************************************************************/ + +#include + +#include +#include +#include +#include + +///< TODO:SPI_CTRLR0_TMOD_Msk需要根据实际情况进行设置 +#define SPI_CTRLR0_TMOD_Msk 3U << 8U ///< 设置SPI模式的寄存器对应的位的掩码 +///< TODO:SPI_CTRLR0_TMOD_RX和SPI_CTRLR0_TMOD_TX需要根据实际情况进行设置 +#define SPI_CTRLR0_TMOD_RX 2U << 8U ///< SPI发送模式 +#define SPI_CTRLR0_TMOD_TX 1U << 8U ///< SPI发送模式 + +static csi_error_t dw_spi_send_intr(csi_spi_t *spi, const void *data, uint32_t size); +static csi_error_t dw_spi_receive_intr(csi_spi_t *spi, void *data, uint32_t size); +static csi_error_t dw_spi_send_receive_intr(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t num); + +static void dw_spi_irqhandler(void *args) +{ + + ///< TODO:获取SPI中断的状态 + + ///< TODO:根据SPI中断的状态进行接收数据的处理,在接收完成后关闭中断;调用用户回调函数 + + ///< TODO:根据SPI中断的状态进行关闭中断,发送数据的处理;调用用户回调函数 + + ///< TODO:根据SPI中断的状态进行异常中断的处理,并清除中断,调用用户回调函数 + +} + +static void dw_spi_dma_event_cb(csi_dma_ch_t *dma, csi_dma_event_t event, void *arg) +{ + csi_spi_t *spi = (csi_spi_t *)dma->parent; + uint32_t mode = 0U; + + ///< TODO:获取SPI传输数据的模式mode:发送模式/接收模式/发送&接收模式 + + if (event == DMA_EVENT_TRANSFER_DONE) { + /* process end of transmit */ + if ((spi->tx_dma != NULL) && (spi->tx_dma->ch_id == dma->ch_id)) { + ///< 关闭DMA通道 + csi_dma_ch_stop(dma); + + ///< TODO:关闭DMA发送使能 + + ///< TODO:如果SPI的BUSY在一定时间内处于空闲状态下 + spi->state.writeable = 1U; + spi->tx_size = 0U; + + if ((mode & SPI_CTRLR0_TMOD_Msk) == SPI_CTRLR0_TMOD_TX) { + ///< TODO:设置发送FIFO的触发级别为0 + + if (spi->callback) { + ///< 调用用户回调函数 + spi->callback(spi, SPI_EVENT_SEND_COMPLETE, spi->arg); + } + } else { + if (spi->state.readable == 1U) { + ///< 调用用户回调函数 + spi->callback(spi, SPI_EVENT_SEND_RECEIVE_COMPLETE, spi->arg); + } + } + } else if ((spi->rx_dma != NULL) && (spi->rx_dma->ch_id == dma->ch_id)) { + ///< 关闭DMA通道 + ///< TODO:关闭SPI接收DMA + ///< TODO:设置接收FIFO的触发级别为0 + ///< TODO:设置接收数据的大小为0 + + spi->state.readable = 1U; + spi->rx_size = 0U; + + if ((mode & SPI_CTRLR0_TMOD_Msk) == SPI_CTRLR0_TMOD_RX) { + if (spi->callback) { + ///< 调用用户回调函数 + spi->callback(spi, SPI_EVENT_RECEIVE_COMPLETE, spi->arg); + } + } else { + if (spi->state.writeable == 1U) { + ///< 调用用户回调函数 + spi->callback(spi, SPI_EVENT_SEND_RECEIVE_COMPLETE, spi->arg); + } + } + } + } +} + +csi_error_t csi_spi_init(csi_spi_t *spi, uint32_t idx) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + ///< 获取中断号、基地址等相关信息 + if (target_get(DEV_DW_SPI_TAG, idx, &spi->dev) != CSI_OK) { + ret = CSI_ERROR; + } else { + spi->state.writeable = 1U; + spi->state.readable = 1U; + spi->state.error = 0U; + spi->send = NULL; + spi->receive = NULL; + spi->send_receive = NULL; + spi->rx_dma = NULL; + spi->tx_dma = NULL; + spi->rx_data = NULL; + spi->tx_data = NULL; + spi->callback = NULL; + spi->arg = NULL; + spi->priv = 0; + + ///< TODO:关闭SPI所有的中断 + ///< TODO:关闭SPI + + } + + return ret; +} + +void csi_spi_uninit(csi_spi_t *spi) +{ + CSI_PARAM_CHK_NORETVAL(spi); + + ///< TODO:复位SPI使用到的寄存器 + + ///< 禁止中断控制器对应的中断,注销中断服务函数 + csi_irq_disable((uint32_t)spi->dev.irq_num); + csi_irq_detach((uint32_t)spi->dev.irq_num); +} + +csi_error_t csi_spi_attach_callback(csi_spi_t *spi, void *callback, void *arg) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + CSI_PARAM_CHK(callback, CSI_ERROR); + + ///< 注册用户回调函数 + spi->callback = callback; + spi->arg = arg; + spi->send = NULL; + spi->receive = NULL; + spi->send_receive = NULL; + + return CSI_OK; +} + + +void csi_spi_detach_callback(csi_spi_t *spi) +{ + CSI_PARAM_CHK_NORETVAL(spi); + + ///< 注销用户回调函数 + spi->callback = NULL; + spi->arg = NULL; + spi->send = NULL; + spi->receive = NULL; + spi->send_receive = NULL; +} + + +csi_error_t csi_spi_mode(csi_spi_t *spi, csi_spi_mode_t mode) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + switch (mode) { + case SPI_MASTER: + ///< TODO:设置SPI为主机模式 + break; + + case SPI_SLAVE: + ///< TODO:设置SPI为从机模式 + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +csi_error_t csi_spi_cp_format(csi_spi_t *spi, csi_spi_cp_format_t format) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + switch (format) { + case SPI_FORMAT_CPOL0_CPHA0: + ///< TODO:设置SPI时钟的极性 + ///< TODO:设置SPI时钟的相位 + break; + + case SPI_FORMAT_CPOL0_CPHA1: + ///< TODO:设置SPI时钟的极性 + ///< TODO:设置SPI时钟的相位 + break; + + case SPI_FORMAT_CPOL1_CPHA0: + ///< TODO:设置SPI时钟的极性 + ///< TODO:设置SPI时钟的相位 + break; + + case SPI_FORMAT_CPOL1_CPHA1: + ///< TODO:设置SPI时钟的极性 + ///< TODO:设置SPI时钟的相位 + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +uint32_t csi_spi_baud(csi_spi_t *spi, uint32_t baud) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + CSI_PARAM_CHK(baud, CSI_ERROR); + + uint32_t freq = 0U; + + ///< TODO:根据SPI工作频率设置传输频率(baud) + ///< TODO:获取SPI时钟的分频div + ///< TODO:根据分频div获取SPI实际传输的频率 + + return freq; + +} + +csi_error_t csi_spi_frame_len(csi_spi_t *spi, csi_spi_frame_len_t length) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + if ((length < SPI_FRAME_LEN_4) || (length > SPI_FRAME_LEN_16)) { + ret = CSI_ERROR; + } else { + ///< TODO:设置SPI数据帧的大小 + } + + return ret; +} + +int32_t csi_spi_send(csi_spi_t *spi, const void *data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + int32_t ret = CSI_OK; + + if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) { + ret = CSI_BUSY; + return ret; + } + + spi->state.writeable = 0U; + + ///< TODO:关闭SPI + ///< TODO:设置SPI为发送模式 + ///< TODO:设置SPI发送FIFO的阈值 + ///< TODO:打开SPI + + + ///< TODO:轮询发送数据,超时则超时退出 + ///< TODO:发送完成后在一定时间内判断发送FIFO是否为空,空则退出,不空则超时退出 + ///< TODO:发送完成后在一定时间内判断SPI BUSY是否为0,0则退出,不为0则超时退出 + + spi->state.writeable = 1U; + + return ret; +} + +csi_error_t csi_spi_send_async(csi_spi_t *spi, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) { + ret = CSI_BUSY; + } + + if ((ret == CSI_OK) && (spi->callback != NULL)) { + if (spi->send) { + spi->state.writeable = 0U; + ///< TODO:调用spi->send发送数据 + } else { + spi->state.writeable = 0U; + ///< 注册SPI的中断服务函数,使能中断控制器对应的中断 + csi_irq_attach((uint32_t)spi->dev.irq_num, &dw_spi_irqhandler, &spi->dev); + csi_irq_enable((uint32_t)spi->dev.irq_num); + ///< TODO:调用dw_spi_send_intr中断模式发送数据 + } + } else { + ret = CSI_ERROR; + } + + return ret; +} + +static csi_error_t dw_spi_send_intr(csi_spi_t *spi, const void *data, uint32_t size) +{ + csi_error_t ret = CSI_OK; + spi->tx_data = (uint8_t *)data; + + ///< TODO:关闭SPI + ///< TODO:设置SPI为发送模式 + ///< TODO:设置SPI发送FIFO的阈值 + ///< TODO:打开SPI + ///< TODO:打开SPI发送FIFO空中断 + + return ret; +} + +static csi_error_t dw_spi_send_dma(csi_spi_t *spi, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + csi_dma_ch_config_t config; + csi_dma_ch_t *dma_ch; + csi_error_t ret = CSI_OK; + + dma_ch = (csi_dma_ch_t *)spi->tx_dma; + spi->tx_data = (uint8_t *)data; + memset(&config, 0, sizeof(csi_dma_ch_config_t)); + + ///< TODO:配置DMA的config.src_tw和config.dst_tw + config.src_inc = DMA_ADDR_INC; + config.dst_inc = DMA_ADDR_CONSTANT; + config.trans_dir = DMA_MEM2PERH; + ///< TODO:配置SPI的硬件握手号config.handshake + + ///< 配置DMA通道 + csi_dma_ch_config(dma_ch, &config); + + ///< TODO:关闭SPI + ///< TODO:设置SPI为发送模式 + ///< TODO:使能SPI发送DMA + + soc_dcache_clean_invalid_range((unsigned long)spi->tx_data, size); + ///< TODO:调用csi_dma_ch_start打开SPI发送数据的DMA通道 + + ///< TODO:打开SPI + + return ret; +} + +int32_t csi_spi_receive(csi_spi_t *spi, void *data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + int32_t ret = CSI_OK; + + if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) { + ret = CSI_BUSY; + return ret; + } + + spi->state.readable = 0U; + spi->rx_data = (uint8_t *)data; + + ///< 关闭SPI + ///< 设置SPI为接收模式 + ///< 设置SPI接收数据的大小 + ///< 打开SPI + + ///< TODO:轮询接收数据,超时则超时退出 + ///< TODO:接收完成后再一定时间内判断SPI BUSY是否为0,为0则退出,不为0则超时退出 + + spi->state.readable = 1U; + + return ret; +} + + +csi_error_t csi_spi_receive_async(csi_spi_t *spi, void *data, uint32_t size) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) { + ret = CSI_BUSY; + } else { + + if ((ret == CSI_OK) && (spi->callback != NULL)) { + if (spi->receive) { + spi->state.readable = 0U; + ret = spi->receive(spi, data, size); + } else { + spi->state.readable = 0U; + ///< 注册SPI的中断服务函数,使能中断控制器对应的中断 + csi_irq_attach((uint32_t)spi->dev.irq_num, &dw_spi_irqhandler, &spi->dev); + csi_irq_enable((uint32_t)spi->dev.irq_num); + ///< 调用dw_spi_receive_intr中断模式接收数据 + ret = dw_spi_receive_intr(spi, data, size); + } + } else { + ret = CSI_ERROR; + } + } + + return ret; +} + +static csi_error_t dw_spi_receive_intr(csi_spi_t *spi, void *data, uint32_t size) +{ + csi_error_t ret = CSI_OK; + + spi->rx_data = (uint8_t *)data; + + ///< TODO:关闭SPI + ///< TODO:设置SPI为接收模式 + ///< TODO:设置SPI接收数据的大小 + ///< TODO:设置SPI接收FIFO的阈值 + ///< TODO:打开SPI + ///< TODO:打开SPI接收FIFO满中断 + + ///< TODO:如果SPI工作在主机模式下 + ///< TODO:写SPI数据寄存器为0 + + return ret; +} + +static csi_error_t dw_spi_receive_dma(csi_spi_t *spi, void *data, uint32_t size) +{ + csi_dma_ch_config_t config; + csi_dma_ch_t *dma_ch; + csi_error_t ret = CSI_OK; + + dma_ch = (csi_dma_ch_t *)spi->rx_dma; + spi->rx_data = (uint8_t *)data; + memset(&config, 0, sizeof(csi_dma_ch_config_t)); + + ///< TODO:配置DMA的config.src_tw和config.dst_tw + config.src_inc = DMA_ADDR_CONSTANT; + config.dst_inc = DMA_ADDR_INC; + config.trans_dir = DMA_PERH2MEM; + ///< TODO:配置SPI的硬件握手号config.handshake + + ///< 配置DMA通道 + csi_dma_ch_config(dma_ch, &config); + + ///< TODO:关闭SPI + ///< TODO:设置SPI为接收模式 + ///< TODO:设置SPI接收数据的大小 + ///< TODO:设置SPI接收FIFO的触发级别 + ///< TODO:使能SPI接收DMA + + soc_dcache_clean_invalid_range((unsigned long)spi->rx_data, size); + ///< TODO:调用csi_dma_ch_start打开SPI接收数据的DMA通道 + + ///< TODO:打开SPI + + ///< TODO:如果SPI工作在主机模式下 + ///< TODO:写SPI数据寄存器为0 + + return ret; +} + +int32_t csi_spi_send_receive(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + CSI_PARAM_CHK(data_out, CSI_ERROR); + CSI_PARAM_CHK(data_in, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + int32_t ret = CSI_OK; + + if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) { + ret = CSI_BUSY; + return ret; + } + + spi->state.writeable = 0U; + spi->state.readable = 0U; + + ///< TODO:关闭SPI + ///< TODO:设置SPI为发送和接收模式 + ///< TODO:设置SPI发送FIFO的阈值 + ///< TODO:设置SPI接收FIFO的阈值 + ///< TODO:打开SPI + + ///< TODO:轮询发送数据 + ///< TODO:轮询接收数据 + ///< TODO:超时退出 + ///< TODO:在一定时间内判断SPI的BUSY是否为0,为0退出,否则超时退出 + + spi->state.writeable = 1U; + spi->state.readable = 1U; + + return ret; +} + + +csi_error_t csi_spi_send_receive_async(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + CSI_PARAM_CHK(data_out, CSI_ERROR); + CSI_PARAM_CHK(data_in, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) { + ret = CSI_BUSY; + } + + if ((ret == CSI_OK) && (spi->callback != NULL)) { + if (spi->send_receive) { + spi->state.readable = 0U; + spi->state.writeable = 0U; + ret = spi->send_receive(spi, data_out, data_in, size); + } else { + spi->state.readable = 0U; + spi->state.writeable = 0U; + ///< 注册SPI的中断服务函数,使能中断控制器对应的中断 + csi_irq_attach((uint32_t)spi->dev.irq_num, &dw_spi_irqhandler, &spi->dev); + csi_irq_enable((uint32_t)spi->dev.irq_num); + ///< 调用dw_spi_send_receive_intr中断模式发送接收数据 + ret = dw_spi_send_receive_intr(spi, data_out, data_in, size); + } + } else { + ret = CSI_ERROR; + } + + return ret; +} + +static csi_error_t dw_spi_send_receive_intr(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size) +{ + csi_error_t ret = CSI_OK; + + spi->tx_data = (uint8_t *)data_out; + spi->rx_data = (uint8_t *)data_in; + + ///< TODO:关闭SPI + ///< TODO:设置SPI为发送接收模式 + ///< TODO:设置接收数据的大小 + ///< TODO:设置发送FIFO的阈值 + ///< TODO:设置接收FIFO的阈值 + ///< TODO:打开SPI + ///< TODO:打开SPI接收FIFO满中断 + ///< TODO:打开SPI发送FIFO空中断 + + return ret; +} + +static csi_error_t dw_spi_send_receive_dma(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size) +{ + csi_dma_ch_config_t config; + csi_dma_ch_t *dma_ch; + csi_error_t ret = CSI_OK; + spi->tx_data = (uint8_t *)data_out; + memset(&config, 0, sizeof(csi_dma_ch_config_t)); + + ///< TODO:配置DMA的config.src_tw和config.dst_tw + + spi->rx_data = (uint8_t *)data_in; + + dma_ch = (csi_dma_ch_t *)spi->tx_dma; + config.src_inc = DMA_ADDR_INC; + config.dst_inc = DMA_ADDR_CONSTANT; + config.trans_dir = DMA_MEM2PERH; + ///< TODO:配置SPI的硬件握手号config.handshake + + ///< 配置发送DMA通道 + csi_dma_ch_config(dma_ch, &config); + + dma_ch = (csi_dma_ch_t *)spi->rx_dma; + config.src_inc = DMA_ADDR_CONSTANT; + config.dst_inc = DMA_ADDR_INC; + config.trans_dir = DMA_PERH2MEM; + ///< TODO:配置SPI的硬件握手号config.handshake + + ///< 配置接收DMA通道 + csi_dma_ch_config(dma_ch, &config); + + ///< TODO:关闭SPI + ///< TODO:设置SPI为发送接收模式 + ///< TODO:设置SPI接收数据的大小 + ///< TODO:设置SPI接收数据FIFO的触发级别 + ///< TODO:使能SPI接收DMA + ///< TODO:使能SPI发送DMA + + ///< 打开发送接收的DMA通道 + + soc_dcache_clean_invalid_range((unsigned long)spi->tx_data, size); + soc_dcache_clean_invalid_range((unsigned long)spi->rx_data, size); + ///< TODO:调用csi_dma_ch_start打开SPI接收数据的DMA通道 + ///< TODO:调用csi_dma_ch_start打开SPI发送数据的DMA通道 + + ///< TODO:打开SPI + return ret; +} + +csi_error_t csi_spi_get_state(csi_spi_t *spi, csi_state_t *state) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + CSI_PARAM_CHK(state, CSI_ERROR); + + *state = spi->state; + return CSI_OK; +} + +csi_error_t csi_spi_link_dma(csi_spi_t *spi, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma) +{ + CSI_PARAM_CHK(spi, CSI_ERROR); + + csi_error_t ret = CSI_OK; + + if (tx_dma != NULL) { + tx_dma->parent = spi; + ///< 申请DMA通道 + ret = csi_dma_ch_alloc(tx_dma, -1, -1); + + if (ret == CSI_OK) { + ///< 注册DMA传输完成中断回调服务函数 + csi_dma_ch_attach_callback(tx_dma, dw_spi_dma_event_cb, NULL); + spi->tx_dma = tx_dma; + spi->send = dw_spi_send_dma; + } else { + tx_dma->parent = NULL; + } + } else { + if (spi->tx_dma) { + ///< 注销DMA传输完成中断回调服务函数,释放DMA通道 + csi_dma_ch_detach_callback(spi->tx_dma); + csi_dma_ch_free(spi->tx_dma); + spi->tx_dma = NULL; + } + + spi->send = NULL; + } + + if (ret == CSI_OK) { + if (rx_dma != NULL) { + rx_dma->parent = spi; + ///< 申请DMA通道 + ret = csi_dma_ch_alloc(rx_dma, -1, -1); + + if (ret == CSI_OK) { + ///< 注册DMA传输完成中断回调服务函数 + csi_dma_ch_attach_callback(rx_dma, dw_spi_dma_event_cb, NULL); + spi->rx_dma = rx_dma; + ///< 调用DMA接收函数开启DMA的接收 + spi->receive = dw_spi_receive_dma; + } else { + rx_dma->parent = NULL; + } + } else { + if (spi->rx_dma) { + ///< 注销DMA传输完成中断回调服务函数,释放DMA通道 + csi_dma_ch_detach_callback(spi->rx_dma); + csi_dma_ch_free(spi->rx_dma); + spi->rx_dma = NULL; + } + + spi->receive = NULL; + } + } + + + if (ret == CSI_OK) { + if ((tx_dma != NULL) && (rx_dma != NULL)) { + ///< 调用DMA发送接收函数开启DMA的发送接收 + spi->send_receive = dw_spi_send_receive_dma; + } else { + spi->send_receive = NULL; + } + } + + return ret; +} + +void csi_spi_select_slave(csi_spi_t *spi, uint32_t slave_num) +{ + CSI_PARAM_CHK_NORETVAL(spi); + + ///< TODO:使能SPI的从机 +} + +#ifdef CONFIG_PM +csi_error_t dw_spi_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action) +{ + CSI_PARAM_CHK(dev, CSI_ERROR); + + csi_error_t ret = CSI_OK; + csi_pm_dev_t *pm_dev = &dev->pm_dev; + + switch (action) { + case PM_DEV_SUSPEND: + ///< TODO:恢复SPI寄存器 + break; + + case PM_DEV_RESUME: + ///< TODO:保存SPI寄存器 + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +csi_error_t csi_spi_enable_pm(csi_spi_t *spi) +{ + ///< TODO:注册WDT低功耗处理函数dw_spi_pm_action +} + +void csi_spi_disable_pm(csi_spi_t *spi) +{ + csi_pm_dev_unregister(&spi->dev); +} +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/spiflash.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/spiflash.c new file mode 100644 index 00000000000..82d99e29d4d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/spiflash.c @@ -0,0 +1,789 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file spiflash.c + * @brief + * @version + * @date 2020-03-18 + ******************************************************************************/ +#include +#include +#include +#include + +/* FLASH command set */ +#define FLASH_CMD_WRITE_STATUS 0x01U +#define FLASH_CMD_READ_STATUS1 0x05U +#define FLASH_CMD_READ_STATUS2 0x35U +#define FLASH_CMD_WRITE_ENABLE 0x06U +#define FLASH_CMD_READ_JEDEC_ID 0x9FU +#define FLASH_CMD_SECTOR_ERASE 0x20U +#define FLASH_CMD_CHIP_ERASE 0x60U +#define FLASH_CMD_PAGE_PROGRAM 0x02U +#define FLASH_CMD_READ_DATA 0x03U +#define FLASH_CMD_SECTOR_ERASE 0x20U +#define FALSH_CMD_POWER_DOWN 0xB9U +#define FALSH_CMD_RELEASE_POWER_DOWN 0xABU + + +/* FLASH operation parameters */ +#define FLASH_DEFUALT_OPERATION_TIMEOUT 100000U + +#define FLASH_STATUS_BP_Pos 2U +#define FLASH_STATUS_TB_Pos(bp_bits) (bp_bits + FLASH_STATUS_BP_Pos) + +#define FLASH_STATUS_BP_Msk(bp_bits, bp_msk) \ + while(bp_bits--){ \ + bp_msk <<= 1U; \ + bp_msk |= 1U; \ + }; \ + bp_msk <<= FLASH_STATUS_BP_Pos; + +#define FLASH_STATUS_TB_Msk(bp_bits) (0x1U << FLASH_STATUS_TB_Pos(bp_bits)) + +#define SPIFLASH_BASE 0x18000000UL + +typedef enum { + FLASH_ADDR_24, ///< 24bit address + FLASH_ADDR_32, ///< 32bit address +} csi_spiflash_addr_mode_t; + +typedef struct csi_spiflash_param { + + char *flash_name; ///< name string of spiflash + uint32_t flash_id; ///< JEDEC ID = manufature ID <<16 | device ID (ID15~ID0) + csi_spiflash_addr_mode_t addr_mode; ///< flash addr mode(24bit or 32 bit) + uint32_t flash_size; ///< flash chip size + uint32_t sector_size; ///< sector size + uint32_t page_size; ///< page size for read or program + uint32_t has_lock: 1; ///< whether flash support lock function + uint32_t region: 2; ///< spiflash lock region type, pls /ref csi_spiflash_lock_region_t + uint32_t bp_bits: 4; ///< how many block protect bits to protect flash + uint32_t base_protect_size; ///< smallest protect size + uint32_t qe_pos; ///< qe bit position +} csi_spiflash_param_t; + +extern csi_error_t spiflash_config_data_line(csi_spiflash_t *spiflash, csi_spiflash_data_line_t line); + +static int32_t flash_wait_ready(csi_spiflash_t *spiflash) +{ + uint32_t addr, addr_size, size; + uint32_t time_start; + uint8_t cmd; + uint8_t status; + int32_t ret = CSI_TIMEOUT; + int32_t check; + + time_start = csi_tick_get_ms(); + cmd = FLASH_CMD_READ_STATUS1; + addr = 0U; + addr_size = 0U; + size = 1U; + + while ((csi_tick_get_ms() - time_start) < FLASH_DEFUALT_OPERATION_TIMEOUT) { + check = spiflash->spi_receive(spiflash, cmd, addr, addr_size, &status, size); + + if ((check == ( int32_t ) size) && ((status & 0x01U) == 0U)) { + ret = CSI_OK; + break; + } + } + + return ret; +} + +static int32_t spiflash_page_write(csi_spiflash_t *spiflash, uint32_t start_addr, void *data, uint32_t size) +{ + csi_spiflash_param_t *param; + uint32_t addr, addr_size, data_size; + uint8_t cmd; + int32_t ret = 0; + uint32_t count = 0U; + + do { + + cmd = FLASH_CMD_WRITE_ENABLE; + addr = 0U; + addr_size = 0U; + data_size = 0U; + param = (csi_spiflash_param_t *)spiflash->flash_prv_info; + ret = spiflash->spi_send(spiflash, cmd, addr, addr_size, NULL, data_size); + + if (ret < 0) { + break; + } + + ret = flash_wait_ready(spiflash); + + if (ret < 0) { + break; + } + + cmd = FLASH_CMD_PAGE_PROGRAM; + addr = start_addr; + + if (param->addr_mode == FLASH_ADDR_32) { + addr_size = 4U; + } else if (param->addr_mode == FLASH_ADDR_24) { + addr_size = 3U; + } + + data_size = size; + ret = spiflash->spi_send(spiflash, cmd, addr, addr_size, data, data_size); + + if(ret < 0){ + break; + } + else { + count = ( uint32_t )ret; + } + + ret = flash_wait_ready(spiflash); + } while (0); + + if( ret >= 0 ) { + ret = ( int32_t )count; + } + + return ret; +} + +csi_error_t csi_spiflash_get_flash_info(csi_spiflash_t *spiflash, csi_spiflash_info_t *flash_info) +{ + CSI_PARAM_CHK(spiflash, CSI_ERROR); + CSI_PARAM_CHK(flash_info, CSI_ERROR); + + csi_spiflash_param_t *param; + csi_error_t ret = CSI_OK; + + param = (csi_spiflash_param_t *)spiflash->flash_prv_info; + + if (param == NULL) { + ret = CSI_ERROR; + } else { + flash_info->flash_name = param->flash_name; + flash_info->flash_id = param->flash_id; + flash_info->flash_size = param->flash_size; + flash_info->sector_size = param->sector_size; + flash_info->page_size = param->page_size; + flash_info->xip_addr = SPIFLASH_BASE; + } + + return ret; +} + + +int32_t csi_spiflash_read(csi_spiflash_t *spiflash, uint32_t offset, void *data, uint32_t size) +{ + CSI_PARAM_CHK(spiflash, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + uint32_t addr, addr_size; + uint8_t cmd; + int32_t ret; + + cmd = FLASH_CMD_READ_DATA; + addr = offset; + addr_size = 3U; + ret = spiflash->spi_receive(spiflash, cmd, addr, addr_size, data, size); + + return ret; +} + + +int32_t csi_spiflash_program(csi_spiflash_t *spiflash, uint32_t offset, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(spiflash, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + int ret = 0; + uint32_t end_addr, current_size, current_addr, count = 0U; + uint8_t *program_data; + csi_spiflash_param_t *param; + + program_data = (uint8_t *)data; + param = (csi_spiflash_param_t *)spiflash->flash_prv_info; + + /* calculation of the size between the write address and the end of the page */ + current_size = param->page_size - (offset % param->page_size); + + /* check if the size of the data is less than the remaining place in the page */ + if (current_size > size) { + current_size = size; + } + + /* initialize the adress variables */ + current_addr = offset; + end_addr = offset + size; + + /* perform the write page by page */ + do { + ret = spiflash_page_write(spiflash, current_addr, (void *)program_data, current_size); + + if (ret < 0) { + break; + } + else{ + count += ( uint32_t )ret; + } + + /* update the address and size variables for next page programming */ + current_addr += current_size; + program_data += current_size; + current_size = ((current_addr + param->page_size) > end_addr) ? (end_addr - current_addr) : param->page_size; + } while (current_addr < end_addr); + + if( ret >= 0 ){ + ret = ( int32_t )count; + } + + return ret; +} + +csi_error_t csi_spiflash_erase(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size) +{ + CSI_PARAM_CHK(spiflash, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + csi_spiflash_param_t *param; + int32_t ret = 0; + uint32_t addr, addr_size, data_size; + uint8_t cmd; + + param = (csi_spiflash_param_t *)spiflash->flash_prv_info; + + do{ + if (size % param->sector_size) { + ret = CSI_ERROR; + break; + } else if (offset % param->sector_size) { + ret = CSI_ERROR; + break; + } + + if (( offset == 0U ) && ( size == param->flash_size )){ /* chip erase */ + ret = spiflash->spi_send(spiflash, FLASH_CMD_WRITE_ENABLE, 0U, 0U, NULL, 0U); + + if (ret < 0) { + break; + } + + ret = flash_wait_ready(spiflash); + + if (ret < 0) { + break; + } + + ret = spiflash->spi_send(spiflash, FLASH_CMD_CHIP_ERASE, 0U, 0U, NULL, 0U); + + if (ret < 0) { + break; + } + + ret = flash_wait_ready(spiflash); + + if (ret < 0) { + break; + } + } + else{ /* sector erase */ + addr = offset; + + do { + ret = spiflash->spi_send(spiflash, FLASH_CMD_WRITE_ENABLE, 0U, 0U, NULL, 0U); + + if (ret < 0) { + break; + } + + ret = flash_wait_ready(spiflash); + + if (ret < 0) { + break; + } + + cmd = FLASH_CMD_SECTOR_ERASE; + addr_size = 3U; + data_size = 0U; + ret = spiflash->spi_send(spiflash, cmd, addr, addr_size, NULL, data_size); + + if (ret < 0) { + break; + } + + ret = flash_wait_ready(spiflash); + + if (ret < 0) { + break; + } + + addr += param->sector_size; + } while (addr < (offset + size)); + } + } while(0); + + return ( csi_error_t )ret; +} + +csi_error_t csi_spiflash_read_reg(csi_spiflash_t *spiflash, uint8_t cmd_code, uint8_t *data, uint32_t size) +{ + CSI_PARAM_CHK(spiflash, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + int ret = 0; + uint32_t addr, addr_size, data_size; + uint8_t cmd; + + cmd = cmd_code; + addr = 0U; + addr_size = 0U; + data_size = size; + ret = spiflash->spi_receive(spiflash, cmd, addr, addr_size, data, data_size); + + if (ret >= 0) { + ret = CSI_OK; + } + + return ( csi_error_t )ret; +} + +csi_error_t csi_spiflash_write_reg(csi_spiflash_t *spiflash, uint8_t cmd_code, uint8_t *data, uint32_t size) +{ + CSI_PARAM_CHK(spiflash, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + uint32_t addr, addr_size, data_size; + uint8_t cmd; + int ret ; + + do { + + ret = spiflash->spi_send(spiflash, FLASH_CMD_WRITE_ENABLE, 0U, 0U, NULL, 0U); + + if (ret < 0) { + ret = CSI_ERROR; + break; + } + + ret = flash_wait_ready(spiflash); + + if (ret < 0) { + ret = CSI_ERROR; + break; + } + + cmd = cmd_code; + addr = 0U; + addr_size = 0U; + data_size = size; + ret = spiflash->spi_send(spiflash, cmd, addr, addr_size, data, data_size); + + if (ret < 0) { + ret = CSI_ERROR; + break; + } + + ret = flash_wait_ready(spiflash); + + if (ret < 0) { + ret = CSI_ERROR; + break; + } + } while (0); + + return ( csi_error_t )ret; +} + +static int is_top_protect_region(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size) +{ + int i = 0; + uint32_t start_addr, end_addr; + uint32_t lock_start_addr, lock_end_addr; + csi_spiflash_param_t *param; + + param = (csi_spiflash_param_t *)spiflash->flash_prv_info; + start_addr = offset; + end_addr = ( offset + size ) - 1U; + + /* Cheak whether protect region is belong to top protect region */ + lock_start_addr = param->flash_size - param->base_protect_size; + lock_end_addr = param->flash_size - 1U; + + do { + i++; + + if ((start_addr == lock_start_addr) && (end_addr == lock_end_addr)) { + break; + } + + lock_start_addr = param->flash_size - (param->base_protect_size << i); + } while (lock_start_addr >= (param->flash_size / 2U)); + + if(lock_start_addr < (param->flash_size / 2U)) + { + i = -1; + } + return i; +} + +static int is_button_protect_region(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size) +{ + int i = 0; + uint32_t start_addr, end_addr; + uint32_t lock_start_addr, lock_end_addr; + csi_spiflash_param_t *param; + + param = (csi_spiflash_param_t *)spiflash->flash_prv_info; + start_addr = offset; + end_addr = ( offset + size ) - 1U; + + /* Cheak whether protect region is belong to button protect region */ + lock_start_addr = 0U; + lock_end_addr = param->base_protect_size; + + do { + i++; + + if ((start_addr == lock_start_addr) && (end_addr == (lock_end_addr - 1U))) { + break; + } + + lock_end_addr = (param->base_protect_size << i); + } while (lock_end_addr <= (param->flash_size / 2U)); + + if(lock_end_addr > (param->flash_size / 2U)){ + i = -1; + } + + return i; +} + +static int spiflash_location_validate(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size) +{ + csi_spiflash_param_t *param; + int ret = -1; + + param = (csi_spiflash_param_t *)spiflash->flash_prv_info; + + if (is_top_protect_region(spiflash, offset, size) != -1) { + ret = 0; + } else if (is_button_protect_region(spiflash, offset, size) != -1) { + ret = 0; + } else if ((offset == 0U) && (size == param->flash_size)) { + ret = 0; + } + + return ret; +} + + +static int calculate_bp(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size) +{ + int bp = 0; + int tb = 0; + int ret; + uint32_t bp_bits; + csi_spiflash_param_t *param; + + param = (csi_spiflash_param_t *)spiflash->flash_prv_info; + + if ((ret = is_top_protect_region(spiflash, offset, size)) != -1) { + bp = ret; + tb = 0; + ret = bp | (tb << ( int )param->bp_bits); + } else if ((ret = is_button_protect_region(spiflash, offset, size)) != -1) { + bp = ret; + tb = 1; + ret = bp | (tb << ( int )param->bp_bits); + } else if ((offset == 0U) && (size == param->flash_size)) { + bp_bits = param->bp_bits; + + while (bp_bits--) { + bp <<= 1; + bp |= 1; + } + + ret = bp; + } else { + ret = -1; + } + + return ret; +} + +csi_error_t csi_spiflash_lock(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size) +{ + CSI_PARAM_CHK(spiflash, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + int ret; + uint8_t bp; + + do { + + ret = spiflash_location_validate(spiflash, offset, size); + + if (ret == -1) { + break; + } + + ret = calculate_bp(spiflash, offset, size); + + if (ret == -1) { + break; + } + + bp = ( uint8_t )ret << FLASH_STATUS_BP_Pos; + ret = csi_spiflash_write_reg(spiflash, FLASH_CMD_WRITE_STATUS, &bp, 1U); + } while (0); + + return ( csi_error_t )ret; +} + +csi_error_t csi_spiflash_unlock(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size) +{ + CSI_PARAM_CHK(spiflash, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + int32_t ret = 0; + uint8_t data; + uint8_t bp_msk = 0U; + uint8_t bp_bits; + csi_spiflash_param_t *param; + + param = (csi_spiflash_param_t *)spiflash->flash_prv_info; + + do { + + if (spiflash_location_validate(spiflash, offset, size) == -1) { + ret = CSI_ERROR; + } else if (csi_spiflash_is_locked(spiflash, offset, size)) { + + /* Calculate bp msk and tb msk */ + bp_bits = param->bp_bits; + FLASH_STATUS_BP_Msk(bp_bits, bp_msk); + bp_bits = param->bp_bits; + bp_msk |= FLASH_STATUS_TB_Msk(bp_bits); + + /* Clear bp bits and tb bits */ + ret = spiflash->spi_receive(spiflash, FLASH_CMD_READ_STATUS1, 0U, 0U, &data, 1U); + + if (ret < 0) { + ret = CSI_ERROR; + break; + } + + data &= ~bp_msk; + ret = spiflash->spi_send(spiflash, FLASH_CMD_WRITE_ENABLE, 0U, 0U, NULL, 0U); + + if (ret < 0) { + ret = CSI_ERROR; + break; + } + + ret = flash_wait_ready(spiflash); + + if (ret < 0) { + ret = CSI_ERROR; + break; + } + + ret = csi_spiflash_write_reg(spiflash, FLASH_CMD_WRITE_STATUS, &data, 1U); + } + } while (0); + + return ( csi_error_t )ret; +} + + +int csi_spiflash_is_locked(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size) +{ + CSI_PARAM_CHK(spiflash, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + int ret; + uint8_t bp; + uint8_t status; + uint8_t bp_msk = 0U; + uint8_t bp_bits; + csi_spiflash_param_t *param; + + do { + param = (csi_spiflash_param_t *)spiflash->flash_prv_info; + ret = spiflash_location_validate(spiflash, offset, size); + + if (ret == -1) { + ret = 0; + break; + } + + /* Calculate bp value */ + ret = calculate_bp(spiflash, offset, size); + + if (ret == -1) { + ret = 0; + break; + } + + bp = ( uint8_t )ret << FLASH_STATUS_BP_Pos; + + ret = spiflash->spi_receive(spiflash, FLASH_CMD_READ_STATUS1, 0U, 0U, &status, 1U); + if (ret < 0) { + ret = CSI_ERROR; + break; + } + + /* Calculate bp msk and tb msk */ + bp_bits = param->bp_bits; + FLASH_STATUS_BP_Msk(bp_bits, bp_msk); + bp_bits = param->bp_bits; + bp_msk |= FLASH_STATUS_TB_Msk(bp_bits); + + if ((status & bp_msk) == (bp & bp_msk)) { + ret = 1; + } else { + ret = 0; + } + } while (0); + + return ret; +} + +csi_error_t csi_spiflash_config_data_line(csi_spiflash_t *spiflash, csi_spiflash_data_line_t line) +{ + CSI_PARAM_CHK(spiflash, CSI_ERROR); + + int32_t ret = 0; + csi_spiflash_param_t *param; + void *temp; + uint8_t status[2]; + + param = (csi_spiflash_param_t *)spiflash->flash_prv_info; + temp = status; + + do { + + /* config spiflash periphrial data line */ + switch (line) { + case SPIFLASH_DATA_1_LINE: + break; + + case SPIFLASH_DATA_2_LINES: + case SPIFLASH_DATA_4_LINES: + + ret = spiflash->spi_receive(spiflash, FLASH_CMD_READ_STATUS1, 0U, 0U, &status[0], 1U); + + if (ret < 0) { + ret = CSI_ERROR; + break; + } + + ret = spiflash->spi_receive(spiflash, FLASH_CMD_READ_STATUS2, 0U, 0U, &status[1], 1U); + + if (ret < 0) { + ret = CSI_ERROR; + break; + } + + if(param->qe_pos == 1U){ + // Used to adapte GDxxx series SPIFLASH + status[1] |= ((uint8_t)0x1U << param->qe_pos); + ret = csi_spiflash_write_reg(spiflash, 0x31U, &status[1], 1U); + } else { + *(uint16_t *) temp |= ((uint16_t)0x1U << param->qe_pos); + ret = csi_spiflash_write_reg(spiflash, 0x01U, status, 2U); + } + + break; + + default: + ret = CSI_ERROR; + break; + } + + if(ret == 0){ + /* config bus data line*/ + ret = spiflash_config_data_line(spiflash, line); + } + } while (0); + + return ( csi_error_t )ret; +} + +uint32_t csi_spiflash_frequence(csi_spiflash_t *spiflash, uint32_t hz) +{ + CSI_PARAM_CHK(spiflash, 0U); + + return csi_qspi_frequence(&spiflash->spi_qspi.qspi, hz); +} + +void csi_spiflash_power_down(csi_spiflash_t *spiflash) +{ + uint32_t addr, addr_size, data_size; + uint8_t cmd; + + cmd = FLASH_CMD_WRITE_ENABLE; + addr = 0U; + addr_size = 0U; + data_size = 0U; + spiflash->spi_send(spiflash, cmd, addr, addr_size, NULL, data_size); + flash_wait_ready(spiflash); + + cmd = FALSH_CMD_POWER_DOWN; + addr = 0U; + addr_size = 0U; + data_size = 0U; + spiflash->spi_send(spiflash, cmd, addr, addr_size, NULL, data_size); +} + +csi_error_t csi_spiflash_release_power_down(csi_spiflash_t *spiflash) +{ + uint32_t addr, addr_size, data_size; + uint8_t cmd; + + cmd = FALSH_CMD_RELEASE_POWER_DOWN; + addr = 0U; + addr_size = 0U; + data_size = 0U; + spiflash->spi_send(spiflash, cmd, addr, addr_size, NULL, data_size); + return ( csi_error_t )flash_wait_ready(spiflash); +} +#if 0 +ATTRIBUTE_DATA void drv_spiflash_continues_read_mode(csi_spiflash_t *spiflash, bool enable) +{ + csi_qspi_t *qspi =&spiflash->spi_qspi.qspi; + cd_qspi_regs_t *qspi_base = (cd_qspi_regs_t *)HANDLE_REG_BASE(qspi); + + if(enable) { + cd_qspi_config_mode_byte(qspi_base, 0x20U); + cd_qspi_enter_xip_mode(qspi_base); + } else { + // exit continues read mode + cd_qspi_config_mode_byte(qspi_base, 0U); + cd_qspi_exit_xip_mode(qspi_base); + for(uint32_t i = 0U; i < 300U; i++){ + *(volatile uint32_t *)SPIFLASH_BASE; + } + } +} +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/timer.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/timer.c new file mode 100644 index 00000000000..1c25a5a499f --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/timer.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + */ + +/******************************************************* + * @file dw_timer.c + * @brief source file for timer csi driver + * @version V1.0 + * @date 28. Apr 2020 + * ******************************************************/ + +#include +#include +#include +#include "dw_timer_ll.h" + +/** + \brief Timer interrupt handling function + \param[in] arg Callback function member variables + \return None +*/ +void dw_timer_irq_handler(void *arg) +{ + csi_timer_t *timer = (csi_timer_t *)arg; + dw_timer_regs_t *timer_base = (dw_timer_regs_t *)timer->dev.reg_base; + + if (dw_timer_get_int_status(timer_base)) { + if (timer->callback) { + timer->callback(timer, timer->arg); + } + + dw_timer_clear_irq(timer_base); + } +} +#if CONFIG_SUPPORT_NMI_DEMO +void timer_clear_irq() +{ + dw_timer_clear_irq((dw_timer_regs_t*)DW_TIMER4_BASE); +} +#endif +/** + \brief Initialize TIMER Interface. 1. Initializes the resources needed for the TIMER interface 2.registers callback function + \param[in] timer handle timer handle to operate + \param[in] idx timer index + \return error code \ref csi_error_t +*/ +csi_error_t csi_timer_init(csi_timer_t *timer, uint32_t idx) +{ + CSI_PARAM_CHK(timer, CSI_ERROR); + + csi_error_t ret = CSI_OK; + dw_timer_regs_t *timer_base = NULL; + + if (0 == target_get(DEV_DW_TIMER_TAG, idx, &timer->dev)) { + timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer); + memset((void *)timer_base, 0, sizeof(dw_timer_regs_t)); + + } else { + ret = CSI_ERROR; + } + + return ret; +} +/** + \brief De-initialize TIMER Interface. stops operation and releases the software resources used by the interface + \param[in] timer handle timer handle to operate + \return None +*/ +void csi_timer_uninit(csi_timer_t *timer) +{ + CSI_PARAM_CHK_NORETVAL(timer); + dw_timer_regs_t *timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer); + + memset((void *)timer_base, 0, sizeof(dw_timer_regs_t)); +} +/** + \brief Start timer + \param[in] timer handle timer handle to operate + \param[in] timeout_us the timeout for timer + \return error code \ref csi_error_t +*/ +csi_error_t csi_timer_start(csi_timer_t *timer, uint32_t timeout_us) +{ + CSI_PARAM_CHK(timer, CSI_ERROR); + CSI_PARAM_CHK(timeout_us, CSI_ERROR); + csi_error_t ret = CSI_OK; + dw_timer_regs_t *timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer); + uint32_t tmp_load = timeout_us * (soc_get_timer_freq((uint32_t)timer->dev.idx) / 1000000U); + + dw_timer_set_mode_load(timer_base); + dw_timer_write_load(timer_base, tmp_load); + + dw_timer_set_disable(timer_base); + dw_timer_set_enable(timer_base); + dw_timer_set_unmask(timer_base); + + return ret; +} +/** + \brief Stop timer + \param[in] timer handle timer handle to operate + \return None +*/ +void csi_timer_stop(csi_timer_t *timer) +{ + CSI_PARAM_CHK_NORETVAL(timer); + + dw_timer_regs_t *timer_base; + timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer); + + dw_timer_set_mask(timer_base); + dw_timer_set_disable(timer_base); +} +/** + \brief Get timer remaining value + \param[in] timer handle timer handle to operate + \return the remaining value +*/ +uint32_t csi_timer_get_remaining_value(csi_timer_t *timer) +{ + CSI_PARAM_CHK(timer, 0U); + + dw_timer_regs_t *timer_base; + timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer); + return dw_timer_get_current(timer_base); +} +/** + \brief Get timer load value + \param[in] timer handle timer handle to operate + \return the load value +*/ +uint32_t csi_timer_get_load_value(csi_timer_t *timer) +{ + CSI_PARAM_CHK(timer, 0U); + + dw_timer_regs_t *timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer); + + return (dw_timer_read_load(timer_base)); +} +/** + \brief Check timer is running + \param[in] timer handle timer handle to operate + \return true->running, false->stopped +*/ +bool csi_timer_is_running(csi_timer_t *timer) +{ + CSI_PARAM_CHK(timer, false); + + dw_timer_regs_t *timer_base = (dw_timer_regs_t *)HANDLE_REG_BASE(timer); + + return (dw_timer_get_enable(timer_base) ? true : false); +} + +/** + \brief Attach the callback handler to timer + \param[in] timer operate handle. + \param[in] callback callback function + \param[in] arg callback's param + \return error code \ref csi_error_t +*/ +csi_error_t csi_timer_attach_callback(csi_timer_t *timer, void *callback, void *arg) +{ + CSI_PARAM_CHK(timer, CSI_ERROR); + + timer->callback = callback; + timer->arg = arg; + csi_irq_attach((uint32_t)timer->dev.irq_num, &dw_timer_irq_handler, &timer->dev); + csi_irq_enable((uint32_t)timer->dev.irq_num); + + return CSI_OK; +} + +/** + \brief Detach the callback handler + \param[in] timer operate handle. +*/ +void csi_timer_detach_callback(csi_timer_t *timer) +{ + CSI_PARAM_CHK_NORETVAL(timer); + + timer->callback = NULL; + timer->arg = NULL; + csi_irq_disable((uint32_t)timer->dev.irq_num); + csi_irq_detach((uint32_t)timer->dev.irq_num); +} + +#ifdef CONFIG_PM +csi_error_t dw_timer_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action) +{ + CSI_PARAM_CHK(dev, CSI_ERROR); + + csi_error_t ret = CSI_OK; + csi_pm_dev_t *pm_dev = &dev->pm_dev; + + switch (action) { + case PM_DEV_SUSPEND: + csi_pm_dev_save_regs(pm_dev->reten_mem, (uint32_t *)dev->reg_base, 1U); + csi_pm_dev_save_regs(pm_dev->reten_mem + 1, (uint32_t *)(dev->reg_base + 8U), 1U); + break; + + case PM_DEV_RESUME: + csi_pm_dev_restore_regs(pm_dev->reten_mem, (uint32_t *)dev->reg_base, 1U); + csi_pm_dev_restore_regs(pm_dev->reten_mem + 1, (uint32_t *)(dev->reg_base + 8U), 1U); + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +csi_error_t csi_timer_enable_pm(csi_timer_t *timer) +{ + return csi_pm_dev_register(&timer->dev, dw_timer_pm_action, 8U, 0U); +} + +void csi_timer_disable_pm(csi_timer_t *timer) +{ + csi_pm_dev_unregister(&timer->dev); +} +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/trng.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/trng.c new file mode 100644 index 00000000000..809c3d75acb --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/trng.c @@ -0,0 +1,75 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file ck_trng.c + * @brief + * @version + * @date 27. April 2020 + ******************************************************************************/ + +#include +#include +#include +#include + +/** + \brief Get data from the TRNG engine + \param[out] data Pointer to buffer with data get from TRNG + \param[in] num Number of data items,uinit in uint32 + \return error code +*/ +csi_error_t csi_rng_get_multi_word(uint32_t *data, uint32_t num) +{ + csi_error_t ret = CSI_OK; + + CSI_PARAM_CHK(data, CSI_ERROR); + if (num == 0U) { + ret = CSI_ERROR; + }else{ + int i = 0; + while (num) { + ///< TODO:使能trng 模块 + + ///< TODO:等待trng 模块有效 且未超时,超时设置ret并退出循环 + + ///< TODO:获取trng值到data[i] + i++; + num--; + } + } + return ret; +} + +/** + \brief Get data from the TRNG engine + \return error code +*/ +csi_error_t csi_rng_get_single_word(uint32_t* data) +{ + csi_error_t ret = CSI_OK; + CSI_PARAM_CHK(data, CSI_ERROR); + + ///< TODO:使能trng 模块 + + ///< TODO:等待trng 模块有效 且未超时,超时设置ret并退出循环 + + ///< TODO:获取trng值到*data + + return ret; +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/uart.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/uart.c new file mode 100644 index 00000000000..32d393099c7 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/uart.c @@ -0,0 +1,809 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file uart.c + * @brief CSI Source File for uart Driver + * @version V2.01 + * @date 2020-04-09 + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define UART_TIMEOUT 0x10000000U +#define UART_MAX_FIFO 0x10U + +extern uint16_t uart_tx_hs_num[]; +extern uint16_t uart_rx_hs_num[]; +extern const csi_pinmap_t uart_pinmap[]; + +static uint8_t find_max_prime_num(uint32_t num) +{ + uint8_t ret; + + if (!(num % 8U)) { + ret = 8U; + } else if (!(num % 4U)) { + ret = 4U; + } else { + ret = 1U; + } + + return ret; +} + +static void dw_uart_intr_recv_data(csi_uart_t *uart) +{ + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + uint32_t rxfifo_num = 1;/// uart->rx_size) ? uart->rx_size : rxfifo_num; + + if ((uart->rx_data == NULL) || (uart->rx_size == 0U)) { + if (uart->callback) { + uart->callback(uart, UART_EVENT_RECEIVE_FIFO_READABLE, uart->arg); + } else { + do { + dw_uart_getchar(uart_base); + } while (--rxfifo_num); + } + } else { + do { + *uart->rx_data = dw_uart_getchar(uart_base); + uart->rx_size--; + uart->rx_data++; + } while (--rxdata_num); + + if (uart->rx_size == 0U) { + uart->state.readable = 1U; + + if (uart->callback) { + uart->callback(uart, UART_EVENT_RECEIVE_COMPLETE, uart->arg); + } + } + } +} + +static void uart_intr_send_data(csi_uart_t *uart) +{ + uint32_t i = 0U, trans_num = 0U; + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)uart->dev.reg_base; + + if (uart->tx_size > UART_MAX_FIFO) { + trans_num = UART_MAX_FIFO; + } else { + trans_num = uart->tx_size; + } + + for (i = 0U; i < trans_num; i++) { + //dw_uart_putchar(uart_base, *uart->tx_data); + csi_uart_putc(uart, *uart->tx_data); + uart->tx_size--; + uart->tx_data++; + } + + if (uart->tx_size == 0U) { + dw_uart_disable_trans_irq(uart_base); + uart->state.writeable = 1U; + + if (uart->callback) { + uart->callback(uart, UART_EVENT_SEND_COMPLETE, uart->arg); + } + } +} + +static void uart_intr_line_error(csi_uart_t *uart) +{ + uint32_t uart_status; + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + + uart->state.readable = 1U; + uart->state.writeable = 1U; + uart_status = dw_uart_get_line_status(uart_base); + + if (uart->callback) { + if (uart_status & DW_UART_LSR_OE_ERROR) { + uart->callback(uart, UART_EVENT_ERROR_OVERFLOW, uart->arg); + } + + if (uart_status & DW_UART_LSR_PE_ERROR) { + uart->callback(uart, UART_EVENT_ERROR_PARITY, uart->arg); + } + + if (uart_status & DW_UART_LSR_FE_ERROR) { + uart->callback(uart, UART_EVENT_ERROR_FRAMING, uart->arg); + } + + if (uart_status & DW_UART_LSR_BI_SET) { + uart->callback(uart, UART_ENENT_BREAK_INTR, uart->arg); + } + } +} + +void dw_uart_irq_handler(void *arg) +{ + csi_uart_t *uart = (csi_uart_t *)arg; + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)uart->dev.reg_base; + + uint8_t intr_state; + + intr_state = (uint8_t)(uart_base->IIR & 0xfU); + + switch (intr_state) { + case DW_UART_IIR_IID_RECV_LINE_STATUS: /* interrupt source: Overrun/parity/framing errors or break interrupt */ + uart_intr_line_error(uart); + break; + + case DW_UART_IIR_IID_THR_EMPTY: /* interrupt source:sendter holding register empty */ + uart_intr_send_data(uart); + break; + + case DW_UART_IIR_IID_RECV_DATA_AVAIL: /* interrupt source:receiver data available or receiver fifo trigger level reached */ + case DW_UART_IIR_IID_CHARACTER_TIMEOUT: + dw_uart_intr_recv_data(uart); + break; + + default: + break; + } +} + +csi_error_t csi_uart_init(csi_uart_t *uart, uint32_t idx) +{ + CSI_PARAM_CHK(uart, CSI_ERROR); + + csi_error_t ret = CSI_OK; + dw_uart_regs_t *uart_base; + + ret = target_get(DEV_DW_UART_TAG, idx, &uart->dev); + + if (ret == CSI_OK) { + uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + + dw_uart_fifo_init(uart_base); + + uart->rx_size = 0U; + uart->tx_size = 0U; + uart->rx_data = NULL; + uart->tx_data = NULL; + uart->tx_dma = NULL; + uart->rx_dma = NULL; + dw_uart_disable_trans_irq(uart_base); + dw_uart_disable_recv_irq(uart_base); + dw_uart_disable_auto_flow_control(uart_base); + } + + return ret; +} + +void csi_uart_uninit(csi_uart_t *uart) +{ + CSI_PARAM_CHK_NORETVAL(uart); + + dw_uart_regs_t *uart_base; + uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + + uart->rx_size = 0U; + uart->tx_size = 0U; + uart->rx_data = NULL; + uart->tx_data = NULL; + + dw_uart_disable_trans_irq(uart_base); + dw_uart_disable_recv_irq(uart_base); + csi_irq_disable((uint32_t)(uart->dev.irq_num)); + csi_irq_detach((uint32_t)(uart->dev.irq_num)); +} + +ATTRIBUTE_DATA csi_error_t csi_uart_baud(csi_uart_t *uart, uint32_t baud) +{ + CSI_PARAM_CHK(uart, CSI_ERROR); + + int32_t ret = 0; + csi_error_t csi_ret = CSI_OK; + dw_uart_regs_t *uart_base; + uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + + ret = dw_uart_config_baudrate(uart_base, baud, soc_get_uart_freq((uint32_t)(uart->dev.idx))); + + if (ret == 0) { + csi_ret = CSI_OK; + } else { + csi_ret = CSI_ERROR; + } + + return csi_ret; +} + +csi_error_t csi_uart_format(csi_uart_t *uart, csi_uart_data_bits_t data_bits, + csi_uart_parity_t parity, csi_uart_stop_bits_t stop_bits) +{ + CSI_PARAM_CHK(uart, CSI_ERROR); + + int32_t ret = 0; + csi_error_t csi_ret = CSI_OK; + dw_uart_regs_t *uart_base; + uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + + switch (data_bits) { + case UART_DATA_BITS_5: + ret = dw_uart_config_data_bits(uart_base, 5U); + break; + + case UART_DATA_BITS_6: + ret = dw_uart_config_data_bits(uart_base, 6U); + break; + + case UART_DATA_BITS_7: + ret = dw_uart_config_data_bits(uart_base, 7U); + break; + + case UART_DATA_BITS_8: + ret = dw_uart_config_data_bits(uart_base, 8U); + break; + + default: + ret = -1; + break; + } + + if (ret == 0) { + switch (parity) { + case UART_PARITY_NONE: + ret = dw_uart_config_parity_none(uart_base); + break; + + case UART_PARITY_ODD: + ret = dw_uart_config_parity_odd(uart_base); + break; + + case UART_PARITY_EVEN: + ret = dw_uart_config_parity_even(uart_base); + break; + + default: + ret = -1; + break; + } + + if (ret == 0) { + switch (stop_bits) { + case UART_STOP_BITS_1: + ret = dw_uart_config_stop_bits(uart_base, 1U); + break; + + case UART_STOP_BITS_2: + ret = dw_uart_config_stop_bits(uart_base, 2U); + break; + + case UART_STOP_BITS_1_5: + if (data_bits == UART_DATA_BITS_5) { + ret = dw_uart_config_stop_bits(uart_base, 2U); + break; + } + + default: + ret = -1; + break; + } + + if (ret != 0) { + csi_ret = CSI_ERROR; + } + + } else { + csi_ret = CSI_ERROR; + } + + } else { + csi_ret = CSI_ERROR; + } + + return csi_ret; +} + +csi_error_t csi_uart_flowctrl(csi_uart_t *uart, csi_uart_flowctrl_t flowctrl) +{ + CSI_PARAM_CHK(uart, CSI_ERROR); + csi_error_t csi_ret = CSI_OK; + dw_uart_regs_t *uart_base; + uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + + switch (flowctrl) { + case UART_FLOWCTRL_CTS: + dw_uart_wait_idle(uart_base); + dw_uart_enable_auto_flow_control(uart_base); + break; + + case UART_FLOWCTRL_RTS_CTS: + dw_uart_wait_idle(uart_base); + dw_uart_enable_auto_flow_control(uart_base); + break; + + case UART_FLOWCTRL_NONE: + dw_uart_wait_idle(uart_base); + break; + + case UART_FLOWCTRL_RTS: + default: + csi_ret = CSI_UNSUPPORTED; + break; + } + + return csi_ret; +} + +void csi_uart_putc(csi_uart_t *uart, uint8_t ch) +{ + CSI_PARAM_CHK_NORETVAL(uart); + + volatile int i = 10; + uint32_t timeout = UART_TIMEOUT; + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + + while (!dw_uart_putready(uart_base) && timeout--); + + if (timeout) { + //FIXME: fix print luanma on irq-mode sometimes. maybe hw bug + while (i--); + dw_uart_putchar(uart_base, ch); + } +} + +ATTRIBUTE_DATA uint8_t csi_uart_getc(csi_uart_t *uart) +{ + CSI_PARAM_CHK(uart, 0U); + + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + + while (!dw_uart_getready(uart_base)); + + return dw_uart_getchar(uart_base); +} + +int32_t csi_uart_receive(csi_uart_t *uart, void *data, uint32_t size, uint32_t timeout) +{ + CSI_PARAM_CHK(uart, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + + uint8_t *temp_data = (uint8_t *)data; + int32_t recv_num = 0; + uint32_t recv_start, timeout_flag = 0U; + uint32_t intr_en_status; + + recv_start = csi_tick_get_ms(); + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)uart->dev.reg_base; + intr_en_status = dw_uart_get_intr_en_status(uart_base); + dw_uart_disable_recv_irq(uart_base); + + while (recv_num < (int32_t)size) { + while (!dw_uart_getready(uart_base)) { + if ((csi_tick_get_ms() - recv_start) >= timeout) { + timeout_flag = 1U; + break; + } + }; + + if (timeout_flag == 0U) { + *temp_data = dw_uart_getchar(uart_base); + temp_data++; + recv_num++; + recv_start = csi_tick_get_ms(); + } else { + break; + } + } + + dw_uart_set_intr_en_status(uart_base, intr_en_status); + + return recv_num; +} + +csi_error_t dw_uart_receive_intr(csi_uart_t *uart, void *data, uint32_t num) +{ + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + uart->rx_data = (uint8_t *)data; + uart->rx_size = num; + + dw_uart_enable_recv_irq(uart_base); + + return CSI_OK; +} + +csi_error_t csi_uart_receive_async(csi_uart_t *uart, void *data, uint32_t size) +{ + CSI_PARAM_CHK(uart, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(uart->callback, CSI_ERROR); + CSI_PARAM_CHK(uart->receive, CSI_ERROR); + + csi_error_t ret; + + ret = uart->receive(uart, data, size); + + if (ret == CSI_OK) { + uart->state.readable = 0U; + } + + return ret; +} + +int32_t csi_uart_send(csi_uart_t *uart, const void *data, uint32_t size, uint32_t timeout) +{ + /* check data and uart */ + CSI_PARAM_CHK(uart, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(size, CSI_ERROR); + + dw_uart_regs_t *uart_base; + uint8_t *ch = (uint8_t *)data; + int32_t trans_num = 0; + uint32_t send_start, timeout_flag = 0U; + uint32_t intr_en_status; + + uart_base = (dw_uart_regs_t *)uart->dev.reg_base; + /* store the status of intr */ + intr_en_status = dw_uart_get_intr_en_status(uart_base); + dw_uart_disable_trans_irq(uart_base); + + send_start = csi_tick_get_ms(); + + while (trans_num < (int32_t)size) { + while (!dw_uart_putready(uart_base)) { + if ((csi_tick_get_ms() - send_start) >= timeout) { + timeout_flag = 1U; + break; + } + }; + + if (timeout_flag == 0U) { + dw_uart_putchar(uart_base, *ch++); + /* update the timeout */ + send_start = csi_tick_get_ms(); + trans_num++; + } else { + break; + } + } + + dw_uart_set_intr_en_status(uart_base, intr_en_status); + + return trans_num; +} + +csi_error_t dw_uart_send_intr(csi_uart_t *uart, const void *data, uint32_t size) +{ + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)uart->dev.reg_base; + + uart->tx_data = (uint8_t *)data; + uart->tx_size = size; + dw_uart_enable_trans_irq(uart_base); + + return CSI_OK; +} + +csi_error_t csi_uart_send_async(csi_uart_t *uart, const void *data, uint32_t size) +{ + CSI_PARAM_CHK(uart, CSI_ERROR); + CSI_PARAM_CHK(data, CSI_ERROR); + CSI_PARAM_CHK(uart->callback, CSI_ERROR); + CSI_PARAM_CHK(uart->send, CSI_ERROR); + + csi_error_t ret; + ret = uart->send(uart, data, size); + + if (ret == CSI_OK) { + uart->state.writeable = 0U; + } + + return ret; +} + +csi_error_t csi_uart_attach_callback(csi_uart_t *uart, void *callback, void *arg) +{ + CSI_PARAM_CHK(uart, CSI_ERROR); + + dw_uart_regs_t *uart_base; + uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + + uart->callback = callback; + uart->arg = arg; + uart->send = dw_uart_send_intr; + uart->receive = dw_uart_receive_intr; + csi_irq_attach((uint32_t)(uart->dev.irq_num), &dw_uart_irq_handler, &uart->dev); + csi_irq_enable((uint32_t)(uart->dev.irq_num)); + dw_uart_enable_recv_irq(uart_base); + + return CSI_OK; +} + +void csi_uart_detach_callback(csi_uart_t *uart) +{ + CSI_PARAM_CHK_NORETVAL(uart); + + dw_uart_regs_t *uart_base; + uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + + uart->callback = NULL; + uart->arg = NULL; + uart->send = NULL; + uart->receive = NULL; + dw_uart_disable_recv_irq(uart_base); + csi_irq_disable((uint32_t)(uart->dev.irq_num)); + csi_irq_detach((uint32_t)(uart->dev.irq_num)); +} + +csi_error_t csi_uart_get_state(csi_uart_t *uart, csi_state_t *state) +{ + CSI_PARAM_CHK(uart, CSI_ERROR); + CSI_PARAM_CHK(state, CSI_ERROR); + + *state = uart->state; + + return CSI_OK; +} + +static void dw_uart_dma_event_cb(csi_dma_ch_t *dma, csi_dma_event_t event, void *arg) +{ + csi_uart_t *uart = (csi_uart_t *)dma->parent; + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + + if (event == DMA_EVENT_TRANSFER_ERROR) {/* DMA transfer ERROR */ + if ((uart->tx_dma != NULL) && (uart->tx_dma->ch_id == dma->ch_id)) { + csi_dma_ch_stop(dma); + dw_uart_fifo_init(uart_base); + + uart->state.writeable = 1U; + + if (uart->callback) { + uart->callback(uart, UART_EVENT_ERROR_OVERFLOW, uart->arg); + } + } else { + csi_dma_ch_stop(dma); + dw_uart_fifo_init(uart_base); + /* enable received data available */ + dw_uart_enable_recv_irq(uart_base); + + uart->state.readable = 1U; + + if (uart->callback) { + uart->callback(uart, UART_EVENT_ERROR_FRAMING, uart->arg); + } + } + } else if (event == DMA_EVENT_TRANSFER_DONE) {/* DMA transfer complete */ + if ((uart->tx_dma != NULL) && (uart->tx_dma->ch_id == dma->ch_id)) { + + csi_dma_ch_stop(dma); + dw_uart_fifo_init(uart_base); + + uart->state.writeable = 1U; + + if (uart->callback) { + uart->callback(uart, UART_EVENT_SEND_COMPLETE, uart->arg); + } + } else { + csi_dma_ch_stop(dma); + dw_uart_fifo_init(uart_base); + /* enable received data available */ + dw_uart_enable_recv_irq(uart_base); + + uart->state.readable = 1U; + + if (uart->callback) { + uart->callback(uart, UART_EVENT_RECEIVE_COMPLETE, uart->arg); + } + } + } +} + +csi_error_t dw_uart_send_dma(csi_uart_t *uart, const void *data, uint32_t num) +{ + csi_dma_ch_config_t config; + memset(&config, 0, sizeof(csi_dma_ch_config_t)); + uint32_t fcr_reg = UART_FIFO_INIT_CONFIG; + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + csi_dma_ch_t *dma_ch = (csi_dma_ch_t *)uart->tx_dma; + + uart->tx_data = (uint8_t *)data; + uart->tx_size = num; + dw_uart_disable_recv_irq(uart_base); + dw_uart_disable_trans_irq(uart_base); + config.src_inc = DMA_ADDR_INC; + config.dst_inc = DMA_ADDR_CONSTANT; + config.src_tw = DMA_DATA_WIDTH_8_BITS; + config.dst_tw = DMA_DATA_WIDTH_8_BITS; + + /* config for wj_dma */ + config.group_len = find_max_prime_num(num); + config.trans_dir = DMA_MEM2PERH; + + /* config for etb */ + config.handshake = uart_tx_hs_num[uart->dev.idx]; + + csi_dma_ch_config(dma_ch, &config); + + fcr_reg &= ~(DW_UART_FCR_TET_Msk); + + if (config.group_len >= (UART_MAX_FIFO / 2U)) { + fcr_reg |= DW_UART_FCR_TET_FIFO_1_2_FULL; + } else if (config.group_len >= (UART_MAX_FIFO / 4U)) { + fcr_reg |= DW_UART_FCR_TET_FIFO_1_4_FULL; + } else if (config.group_len >= (UART_MAX_FIFO / 8U)) { + fcr_reg |= DW_UART_FCR_TET_FIFO_2_CHAR; + } else { + fcr_reg |= DW_UART_FCR_TET_FIFO_EMTPY; + } + + soc_dcache_clean_invalid_range((unsigned long)uart->tx_data, uart->tx_size); + dw_uart_set_fcr_reg(uart_base, fcr_reg); + csi_dma_ch_start(uart->tx_dma, (void *)uart->tx_data, (uint8_t *) & (uart_base->THR), uart->tx_size); + + return CSI_OK; +} + +csi_error_t dw_uart_receive_dma(csi_uart_t *uart, void *data, uint32_t num) +{ + csi_dma_ch_config_t config; + memset(&config, 0, sizeof(csi_dma_ch_config_t)); + csi_error_t ret = CSI_OK; + uint32_t fcr_reg = UART_FIFO_INIT_CONFIG; + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart); + csi_dma_ch_t *dma = (csi_dma_ch_t *)uart->rx_dma; + + dw_uart_disable_trans_irq(uart_base); + dw_uart_disable_recv_irq(uart_base); + uart->rx_data = (uint8_t *)data; + uart->rx_size = num; + config.src_inc = DMA_ADDR_CONSTANT; + config.dst_inc = DMA_ADDR_INC; + config.src_tw = DMA_DATA_WIDTH_8_BITS; + config.dst_tw = DMA_DATA_WIDTH_8_BITS; + config.group_len = find_max_prime_num(num); + config.trans_dir = DMA_PERH2MEM; + config.handshake = uart_rx_hs_num[uart->dev.idx]; + + ret = csi_dma_ch_config(dma, &config); + + if (ret == CSI_OK) { + + fcr_reg &= ~(DW_UART_FCR_RT_Msk); + + if (config.group_len >= (UART_MAX_FIFO / 2U)) { + fcr_reg |= DW_UART_FCR_RT_FIFO_1_2_FULL; + } else if (config.group_len >= (UART_MAX_FIFO / 4U)) { + fcr_reg |= DW_UART_FCR_RT_FIFO_1_4_FULL; + } else { + fcr_reg |= DW_UART_FCR_RT_FIFO_1_CHAR; + } + + soc_dcache_clean_invalid_range((unsigned long)uart->rx_data, uart->rx_size); + dw_uart_set_fcr_reg(uart_base, fcr_reg | DW_UART_FCR_RFIFOR_RESET); + csi_dma_ch_start(uart->rx_dma, (uint8_t *) & (uart_base->RBR), (void *)uart->rx_data, uart->rx_size); + } + + return ret; +} + +csi_error_t csi_uart_link_dma(csi_uart_t *uart, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma) +{ + CSI_PARAM_CHK(uart, CSI_ERROR); + CSI_PARAM_CHK(uart->callback, CSI_ERROR); + csi_error_t ret = CSI_OK; + + if (tx_dma != NULL) { + tx_dma->parent = uart; + ret = csi_dma_ch_alloc(tx_dma, -1, -1); + + if (ret == CSI_OK) { + csi_dma_ch_attach_callback(tx_dma, dw_uart_dma_event_cb, NULL); + uart->tx_dma = tx_dma; + uart->send = dw_uart_send_dma; + } else { + tx_dma->parent = NULL; + } + } else { + if (uart->tx_dma) { + csi_dma_ch_detach_callback(uart->tx_dma); + csi_dma_ch_free(uart->tx_dma); + uart->tx_dma = NULL; + } + + uart->send = dw_uart_send_intr; + } + + if (ret != CSI_ERROR) { + if (rx_dma != NULL) { + rx_dma->parent = uart; + ret = csi_dma_ch_alloc(rx_dma, -1, -1); + + if (ret == CSI_OK) { + csi_dma_ch_attach_callback(rx_dma, dw_uart_dma_event_cb, NULL); + uart->rx_dma = rx_dma; + uart->receive = dw_uart_receive_dma; + } else { + rx_dma->parent = NULL; + } + } else { + if (uart->rx_dma) { + csi_dma_ch_detach_callback(uart->rx_dma); + csi_dma_ch_free(uart->rx_dma); + uart->rx_dma = NULL; + } + + uart->receive = dw_uart_receive_intr; + } + } + return ret; +} + +#ifdef CONFIG_PM +csi_error_t dw_uart_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action) +{ + CSI_PARAM_CHK(dev, CSI_ERROR); + + csi_error_t ret = CSI_OK; + csi_pm_dev_t *pm_dev = &dev->pm_dev; + dw_uart_regs_t *uart_base = (dw_uart_regs_t *)dev->reg_base; + + switch (action) { + case PM_DEV_SUSPEND: + dw_uart_fifo_disable(uart_base); + dw_uart_fifo_enable(uart_base); + dw_uart_wait_idle(uart_base); + uart_base->LCR |= DW_UART_LCR_DLAB_EN; + csi_pm_dev_save_regs(pm_dev->reten_mem, (uint32_t *)dev->reg_base, 2U); + uart_base->LCR &= (~DW_UART_LCR_DLAB_EN); + csi_pm_dev_save_regs(pm_dev->reten_mem + 2, (uint32_t *)(dev->reg_base + 4U), 1U); + csi_pm_dev_save_regs(pm_dev->reten_mem + 2 + 1, (uint32_t *)(dev->reg_base + 12U), 2U); + break; + + case PM_DEV_RESUME: + dw_uart_fifo_disable(uart_base); + dw_uart_fifo_enable(uart_base); + dw_uart_wait_idle(uart_base); + uart_base->LCR |= DW_UART_LCR_DLAB_EN; + csi_pm_dev_restore_regs(pm_dev->reten_mem, (uint32_t *)dev->reg_base, 2U); + uart_base->LCR &= (~DW_UART_LCR_DLAB_EN); + csi_pm_dev_restore_regs(pm_dev->reten_mem + 2, (uint32_t *)(dev->reg_base + 4U), 1U); + csi_pm_dev_restore_regs(pm_dev->reten_mem + 2 + 1, (uint32_t *)(dev->reg_base + 12U), 2U); + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +csi_error_t csi_uart_enable_pm(csi_uart_t *uart) +{ + return csi_pm_dev_register(&uart->dev, dw_uart_pm_action, 20U, 0U); +} + +void csi_uart_disable_pm(csi_uart_t *uart) +{ + csi_pm_dev_unregister(&uart->dev); +} +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/wdt.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/wdt.c new file mode 100644 index 00000000000..36f9a47aae7 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/drivers/wdt.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + */ + +/******************************************************* + * @file dw_wdt.c + * @brief source file for wdt csi driver + * @version V1.0 + * @date 23. Sep 2020 + * ******************************************************/ + +#include +#include + +void dw_wdt_irq_handler(void *arg) +{ + + ///< TODO:获取WDT的中断状态 + ///< TODO:根据中断状态执行用户回调函数 + +} + +/** + \brief Initialize WDT Interface. Initializes the resources needed for the WDT interface + \param[in] wdt wdt handle to operate + \param[in] idx wdt index + \return error code \ref csi_error_t +*/ +csi_error_t csi_wdt_init(csi_wdt_t *wdt, uint32_t idx) +{ + CSI_PARAM_CHK(wdt, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< 获取中断号、基地址等相关信息 + if (0 == target_get(DEV_DW_WDT_TAG, idx, &wdt->dev)) { + + ///< TODO:复位WDT的控制寄存器 + ///< TODO:复位WDT的超时时间范围寄存器 + ///< TODO:复位重启WDT计数器寄存器 + + } else { + ret = CSI_ERROR; + } + + return ret; +} +/** + \brief De-initialize WDT Interface. stops operation and releases the software resources used by the interface + \param[in] wdt handle to operate + \return None +*/ +void csi_wdt_uninit(csi_wdt_t *wdt) +{ + CSI_PARAM_CHK_NORETVAL(wdt); + + ///< TODO:复位WDT的控制寄存器 + ///< TODO:复位WDT的超时时间范围寄存器 + ///< TODO:复位重启WDT计数器寄存器 + +} +/** + \brief Set the WDT value + \param[in] wdt handle to operate + \param[in] ms the timeout value(ms) + \return error code \ref csi_error_t +*/ +csi_error_t csi_wdt_set_timeout(csi_wdt_t *wdt, uint32_t ms) +{ + CSI_PARAM_CHK(wdt, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< TODO:关闭WDT + + ///< TODO:设置超时时间 + ///< TODO:打开WDT + ///< TODO:重启WDT计数器 + + return ret; +} +/** + \brief Start the WDT + \param[in] wdt handle to operate + \return error code \ref csi_error_t +*/ +csi_error_t csi_wdt_start(csi_wdt_t *wdt) +{ + CSI_PARAM_CHK(wdt, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< TODO:打开WDT + ///< TODO:重启WDT计数器 + + return ret; +} +/** + \brief Stop the WDT + \param[in] wdt handle to operate + \return None +*/ +void csi_wdt_stop(csi_wdt_t *wdt) +{ + CSI_PARAM_CHK_NORETVAL(wdt); + + ///< TODO:关闭WDT +} +/** + \brief Feed the WDT + \param[in] wdt handle to operate + \return error code \ref csi_error_t +*/ +csi_error_t csi_wdt_feed(csi_wdt_t *wdt) +{ + CSI_PARAM_CHK(wdt, CSI_ERROR); + csi_error_t ret = CSI_OK; + + ///< TODO:喂狗 + + return ret; +} + +/** + \brief Get the remaining time to timeout + \param[in] wdt handle to operate + \return tne remaining time of wdt(ms) +*/ +uint32_t csi_wdt_get_remaining_time(csi_wdt_t *wdt) +{ + CSI_PARAM_CHK(wdt, 0U); + uint32_t time = 0U; + + ///< TODO:获取前剩余的时间time,单位为ms + + return time; +} + +/** + \brief Check wdt is running + \param[in] wdt handle wdt handle to operate + \return true->running, false->stopped +*/ +bool csi_wdt_is_running(csi_wdt_t *wdt) +{ + CSI_PARAM_CHK(wdt, false); + uint32_t status = 0U; + + ///< TODO:获取WDT是否使能的状态status + + return status; +} + +/** + \brief Attach the callback handler to wdt + \param[in] wdt operate handle + \param[in] callback callback function + \param[in] arg callback's param + \return error code \ref csi_error_t +*/ +csi_error_t csi_wdt_attach_callback(csi_wdt_t *wdt, void *callback, void *arg) +{ + CSI_PARAM_CHK(wdt, CSI_ERROR); + + wdt->callback = callback; + wdt->arg = arg; + ///<注册WDT中断服务函数,使能中断控制器对应的中断 + csi_irq_attach((uint32_t)wdt->dev.irq_num, &dw_wdt_irq_handler, &wdt->dev); + csi_irq_enable((uint32_t)wdt->dev.irq_num); + + ///< TODO:设置WDT超时时产生系统复位 + + return CSI_OK; +} + +/** + \brief Detach the callback handler + \param[in] wdt operate handle + \return None +*/ +void csi_wdt_detach_callback(csi_wdt_t *wdt) +{ + CSI_PARAM_CHK_NORETVAL(wdt); + + wdt->callback = NULL; + wdt->arg = NULL; + ///<关闭中断控制器对应的中断,注销WDT中断服务函数 + csi_irq_disable((uint32_t)wdt->dev.irq_num); + csi_irq_detach((uint32_t)wdt->dev.irq_num); + + ///< TODO:复位WDT超时时产生系统复位的功能 + +} + +#ifdef CONFIG_PM +csi_error_t dw_wdt_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action) +{ + CSI_PARAM_CHK(dev, CSI_ERROR); + + csi_error_t ret = CSI_OK; + csi_pm_dev_t *pm_dev = &dev->pm_dev; + + switch (action) { + case PM_DEV_SUSPEND: + ///< TODO:恢复WDT寄存器 + break; + + case PM_DEV_RESUME: + ///< TODO:保存WDT寄存器 + break; + + default: + ret = CSI_ERROR; + break; + } + + return ret; +} + +csi_error_t csi_wdt_enable_pm(csi_wdt_t *wdt) +{ + ///< TODO:注册WDT低功耗处理函数dw_wdt_pm_action +} + +void csi_wdt_disable_pm(csi_wdt_t *wdt) +{ + csi_pm_dev_unregister(&wdt->dev); +} +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/SConscript b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/SConscript new file mode 100644 index 00000000000..49d56d78e3d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/SConscript @@ -0,0 +1,15 @@ +from building import * +import os + +cwd = GetCurrentDir() +CPPPATH = [cwd] +src = ['irq.c'] +src += ['irq_port.c'] +src += ['sys_clk.c'] +src += ['tick.c'] +src += ['target_get.c'] +src += ['devices.c'] + +group = DefineGroup('sys', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/devices.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/devices.c new file mode 100644 index 00000000000..bb4a04d1465 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/devices.c @@ -0,0 +1,69 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const csi_perip_info_t g_soc_info[] = { + {DW_UART0_BASE, DW_UART0_IRQn, 0, DEV_DW_UART_TAG}, + {DW_TIMER0_BASE, TIM0_IRQn, 0, DEV_DW_TIMER_TAG}, + {DW_TIMER1_BASE, TIM1_IRQn, 1, DEV_DW_TIMER_TAG}, + {DW_TIMER2_BASE, TIM2_IRQn, 2, DEV_DW_TIMER_TAG}, + {DW_TIMER3_BASE, TIM3_IRQn, 3, DEV_DW_TIMER_TAG}, +#if CONFIG_SUPPORT_NMI_DEMO + {DW_TIMER4_BASE, FAKE_IRQ_TIMER4, 4, DEV_DW_TIMER_TAG}, +#endif + {0, 0, 0, 0} +}; + +const uint8_t g_dma_chnum[] = {}; + +const uint16_t uart_tx_hs_num[1] = {}; +const uint16_t uart_rx_hs_num[1] = {}; + +const csi_dma_ch_desc_t uart0_dma_ch_list[] = { + {0xff, 0xff} +}; + +const csi_dma_ch_spt_list_t dma_spt_list[] = { + {0xFFFFU, 0xFFU, NULL}, +}; + +const csi_pinmap_t gpio_pinmap[] = { + {0xFFFFFFFFU, 0xFFU, 0xFFU, 0xFFFFFFFFU }, +}; + +const csi_pinmap_t uart_pinmap[] = { + {0xFFFFFFFFU, 0xFFU, 0xFFU, 0xFFFFFFFFU }, +}; + +const csi_clkmap_t clk_map[] = { + {0xFFFFFFFFU, 0xFFFFU, 0xFFU} +}; + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/irq.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/irq.c new file mode 100644 index 00000000000..2d657c420cd --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/irq.c @@ -0,0 +1,240 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#if CONFIG_AOS_OSAL +#include +#endif + +extern void Default_Handler(void); +extern uint32_t soc_irq_get_irq_num(void); +extern void soc_irq_end(uint32_t irq_num); + +#if CONFIG_AOS_OSAL +#define CSI_INTRPT_ENTER() aos_kernel_intrpt_enter() +#define CSI_INTRPT_EXIT() aos_kernel_intrpt_exit() +#else +#ifdef CONFIG_KERNEL_FREERTOS +extern int freertos_intrpt_enter(void); +extern int freertos_intrpt_exit(void); +#define CSI_INTRPT_ENTER() freertos_intrpt_enter() +#define CSI_INTRPT_EXIT() freertos_intrpt_exit() +#elif defined(CONFIG_KERNEL_RTTHREAD) +extern void rt_interrupt_enter(void); +extern void rt_interrupt_leave(void); +#define CSI_INTRPT_ENTER() rt_interrupt_enter() +#define CSI_INTRPT_EXIT() rt_interrupt_leave() +#else +#define CSI_INTRPT_ENTER() +#define CSI_INTRPT_EXIT() +#endif +#endif /* end CONFIG_AOS_OSAL */ + +#if defined(CONFIG_SMP) && CONFIG_SMP +volatile uint32_t g_irq_nested_level[CONFIG_NR_CPUS]; +#else +volatile uint32_t g_irq_nested_level; +#endif +csi_dev_t *g_irq_table[CONFIG_IRQ_NUM]; + +/** + \brief register irq handler(deprecated). + \param[in] irq_num Number of IRQ. + \return None. +*/ +void csi_irq_attach(uint32_t irq_num, void *irq_handler, csi_dev_t *dev) +{ + dev->irq_handler = irq_handler; + g_irq_table[irq_num] = dev; +} + +/** + \brief Attach irq handler2 for compatible(Recommended). + \param[in] irq_num Number of IRQ. + \param[in] irq_handler2 IRQ Handler. + \param[in] dev The dev to operate + \param[in] arg user data of irq_handler2 + \return None. +*/ +void csi_irq_attach2(uint32_t irq_num, void *irq_handler2, csi_dev_t *dev, void *arg) +{ + dev->arg = arg; + dev->irq_handler2 = irq_handler2; + g_irq_table[irq_num] = dev; +} + +/** + \brief unregister irq handler. + \param[in] irq_num Number of IRQ. + \param[in] irq_handler IRQ Handler. + \return None. +*/ +void csi_irq_detach(uint32_t irq_num) +{ + g_irq_table[irq_num] = NULL; +} + +/** + \brief gets whether in irq context + \return true or false. +*/ +bool csi_irq_context(void) +{ +#if defined(CONFIG_SMP) && CONFIG_SMP + return ((g_irq_nested_level[csi_get_cpu_id()] > 0U) ? true : false); +#else + return ((g_irq_nested_level > 0U) ? true : false); +#endif +} + +#if CONFIG_CPU_XUANTIE_E9XX +static volatile int g_nmi_cnt; +__attribute__((weak)) void handle_nmi_exception(void) +{ + g_nmi_cnt++; +#if CONFIG_SUPPORT_NMI_DEMO + extern void timer_clear_irq(); + timer_clear_irq(); +#endif +} +#else +//FIXME: +extern void tick_irq_handler(void *arg); +void CORET_IRQHandler(void) +{ +#if defined(CONFIG_SMP) && CONFIG_SMP + g_irq_nested_level[csi_get_cpu_id()]++; +#else + g_irq_nested_level++; +#endif + CSI_INTRPT_ENTER(); + tick_irq_handler(NULL); + CSI_INTRPT_EXIT(); +#if defined(CONFIG_SMP) && CONFIG_SMP + g_irq_nested_level[csi_get_cpu_id()]--; +#else + g_irq_nested_level--; +#endif +} +#endif /* CONFIG_CPU_XUANTIE_E9XX */ + +#if CONFIG_ECC_L1_ENABLE || CONFIG_ECC_L2_ENABLE +static struct { + int err_cnt_l1; + int err_cnt_l2; +} g_ecc_stat; + +void __attribute__((weak)) ecc_l1_irqhandler(void *arg) +{ + g_ecc_stat.err_cnt_l1++; + + if (!(__get_MCER() >> 31) || (__get_MCER() & (0x1 << 30))) { + /* may be ecc fatal error happens */ + while (1); + } else { + /* clear MCER EE_VLD */ +#if __riscv_xlen == 32 + __set_MCER(0); + __set_MCERH(0); +#else + __set_MCER(0); +#endif + } +} + +void __attribute__((weak)) ecc_l2_irqhandler(void *arg) +{ + g_ecc_stat.err_cnt_l2++; + +#if __riscv_xlen == 32 + if((__get_MCER2H() >> 30) == 0x2) { + /* clear MCER EE_VLD */ + __set_MCER2(0); + __set_MCER2H(0); + } else { + /* may be ecc fatal error happens */ + while (1); + } +#else + if((__get_MCER2() >> 62) == 0x2) { + /* clear MCER EE_VLD */ + __set_MCER2(0); + } else { + /* may be ecc fatal error happens */ + while (1); + } +#endif +} + +void ECC_L1_IRQHandler(void) +{ +#if defined(CONFIG_SMP) && CONFIG_SMP + g_irq_nested_level[csi_get_cpu_id()]++; +#else + g_irq_nested_level++; +#endif + CSI_INTRPT_ENTER(); + ecc_l1_irqhandler(NULL); + CSI_INTRPT_EXIT(); +#if defined(CONFIG_SMP) && CONFIG_SMP + g_irq_nested_level[csi_get_cpu_id()]--; +#else + g_irq_nested_level--; +#endif +} + +#endif +/** + \brief dispatching irq handlers(only handle external irq) + \return None. +*/ +void do_irq(void) +{ + uint32_t irqn; + +#if defined(CONFIG_SMP) && CONFIG_SMP + g_irq_nested_level[csi_get_cpu_id()]++; +#else + g_irq_nested_level++; +#endif + CSI_INTRPT_ENTER(); + irqn = soc_irq_get_irq_num(); + if (g_irq_table[irqn]) { + if (g_irq_table[irqn]->irq_handler) + /* for compatibility */ + g_irq_table[irqn]->irq_handler(g_irq_table[irqn]); + else if (g_irq_table[irqn]->irq_handler2) + g_irq_table[irqn]->irq_handler2(irqn, g_irq_table[irqn]->arg); + else + Default_Handler(); + } else { + Default_Handler(); + } + /* clear irq for cxx */ + soc_irq_end(irqn); + CSI_INTRPT_EXIT(); +#if defined(CONFIG_SMP) && CONFIG_SMP + g_irq_nested_level[csi_get_cpu_id()]--; +#else + g_irq_nested_level--; +#endif +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/irq_port.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/irq_port.c new file mode 100644 index 00000000000..7fa2ae9a0ee --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/irq_port.c @@ -0,0 +1,98 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include + +void soc_irq_enable(uint32_t irq_num) +{ + csi_vic_enable_irq((int32_t)irq_num); +} + +void soc_irq_disable(uint32_t irq_num) +{ + csi_vic_disable_irq((int32_t)irq_num); +} + +bool soc_irq_is_enabled(uint32_t irq_num) +{ + bool ret; + + if (csi_vic_get_enabled_irq((int32_t)irq_num)) { + ret = true; + } else { + ret = false; + } + + return ret; +} + +void soc_irq_priority(uint32_t irq_num, uint32_t priority) +{ + csi_vic_set_prio((int32_t)irq_num, priority); +} + +/** + * @brief get external irq number only + * @return irq no + */ +uint32_t soc_irq_get_irq_num(void) +{ +#if CONFIG_CPU_XUANTIE_E9XX + return (__get_MCAUSE() & 0x3FFU); +#else + uint32_t num; +#if CONFIG_INTC_CLIC_PLIC + uint32_t irqn = __get_MCAUSE() & 0x3FFU; + if (irqn == Machine_External_IRQn) { + num = PLIC_Hn_MSCLAIM_VAL(&PLIC->PLIC_H0_MCLAIM, csi_get_cpu_id()); + num += PLIC_IRQ_OFFSET; + } else { + num = irqn; + } +#else +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + num = PLIC_Hn_MSCLAIM_VAL(&PLIC->PLIC_H0_SCLAIM, csi_get_cpu_id()); +#else + num = PLIC_Hn_MSCLAIM_VAL(&PLIC->PLIC_H0_MCLAIM, csi_get_cpu_id()); +#endif +#endif + return num; +#endif /* end exx */ +} + +void soc_irq_end(uint32_t irq_num) +{ +#if CONFIG_CPU_XUANTIE_E9XX + //TODO: +#else +#if CONFIG_INTC_CLIC_PLIC + if (irq_num <= PLIC_IRQ_OFFSET) { + return; + } + irq_num -= PLIC_IRQ_OFFSET; +#endif +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + PLIC_Hn_MSCLAIM_VAL(&PLIC->PLIC_H0_SCLAIM, csi_get_cpu_id()) = irq_num; +#else + PLIC_Hn_MSCLAIM_VAL(&PLIC->PLIC_H0_MCLAIM, csi_get_cpu_id()) = irq_num; +#endif +#endif /* end exx */ +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/sys_clk.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/sys_clk.c new file mode 100644 index 00000000000..b7cb966d648 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/sys_clk.c @@ -0,0 +1,96 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include + +uint32_t g_system_clock = IHS_VALUE; + +#if CONFIG_BOARD_XIAOHUI_EVB +uint32_t soc_get_cpu_freq(uint32_t idx) +{ + return 50*1000000; +} + +uint32_t soc_get_coretim_freq(void) +{ + return 25*1000000; +} + +uint32_t soc_get_uart_freq(uint32_t idx) +{ + return 36*1000000; +} + +uint32_t soc_get_timer_freq(uint32_t idx) +{ + return 25*1000000; +} + +#else +uint32_t soc_get_cpu_freq(uint32_t idx) +{ + return g_system_clock; +} + +uint32_t soc_get_cur_cpu_freq(void) +{ + return g_system_clock; +} + +uint32_t soc_get_coretim_freq(void) +{ + return g_system_clock; +} + +uint32_t soc_get_uart_freq(uint32_t idx) +{ + return g_system_clock; +} + +csi_error_t soc_sysclk_config(system_clk_config_t *config) +{ + return CSI_OK; +} + +void soc_reset_uart(uint32_t idx) +{ +} + +uint32_t soc_get_timer_freq(uint32_t idx) +{ + return g_system_clock; +} +#endif + +void soc_clk_enable(int32_t module) +{ +} + +void soc_clk_disable(int32_t module) +{ +} + +void soc_set_sys_freq(uint32_t val) +{ + g_system_clock = val; +} + + diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/target_get.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/target_get.c new file mode 100644 index 00000000000..794c372f670 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/target_get.c @@ -0,0 +1,190 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + + +/****************************************************************************** + * @file target_get.c + * @brief CSI Source File for target API + * @version V1.0 + * @date 9. April 2020 + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +extern csi_perip_info_t g_soc_info[]; +extern const csi_dma_ch_spt_list_t dma_spt_list[]; + +csi_error_t target_get(csi_dev_tag_t dev_tag, uint32_t idx, csi_dev_t *dev) +{ + csi_error_t ret = CSI_OK; + csi_perip_info_t *info; + + if (dev == NULL) { + ret = CSI_ERROR; + } + + ///< 使用包含外设基地址,外设中断号,外设设备号,外设设备类型成员的结构体数组变量初始化info + info = (csi_perip_info_t *)&g_soc_info; + + ///< 获取相应的设备类型和设备号 + while (info->reg_base) { + if ((info->dev_tag == (uint16_t)dev_tag) && (info->idx == (uint8_t)idx)) { + break; + } + + info++; + } + + ///< 初始化设备的统一句柄:基地址,中断号,设备号,设备类型 + if (info->reg_base == 0U) { + ret = CSI_ERROR; + } + + if (ret != CSI_ERROR) { + dev->reg_base = info->reg_base; + dev->irq_num = info->irq_num; + dev->idx = info->idx; + dev->dev_tag = (uint16_t)dev_tag; + } + + return ret; +} + +uint32_t target_pin_to_devidx(pin_name_t pin_name, const csi_pinmap_t *pinmap) +{ + const csi_pinmap_t *map = pinmap; + uint32_t ret = 0xFFFFFFFFU; + + while ((uint32_t)map->pin_name != 0xFFFFFFFFU) { + if ((map->pin_name == pin_name) && (csi_pin_get_mux(pin_name) == map->pin_func)) { + ret = map->idx; + break; + } + + map++; + } + + return ret; +} + +uint32_t target_pin_to_channel(pin_name_t pin_name, const csi_pinmap_t *pinmap) +{ + const csi_pinmap_t *map = pinmap; + uint32_t ret = 0xFFFFFFFFU; + + while ((uint32_t)map->pin_name != 0xFFFFFFFFU) { + if (map->pin_name == pin_name) { + ret = (uint32_t)map->channel; + break; + } + + map++; + } + + return ret; +} + +pin_name_t target_gpio_to_pin(uint8_t gpio_idx, uint8_t channel, const csi_pinmap_t *pinmap) +{ + const csi_pinmap_t *map = pinmap; + pin_name_t ret = (pin_name_t)0xFFU; + + while ((uint32_t)map->pin_name != 0xFFFFFFFFU) { + if ((map->idx == gpio_idx) && (map->channel == channel)) { + ret = map->pin_name; + break; + } + + map++; + } + + return ret; +} + +csi_error_t target_get_optimal_dma_channel(void *dma_list, uint32_t ctrl_num, csi_dev_t *parent_dev, void *ch_info) +{ + uint32_t spt_id, ch_info_id, ctrl_id, ch_id; + int32_t is_find = 0; + csi_error_t csi_ret = CSI_OK; + csi_dma_t **list = (csi_dma_t **)dma_list; + csi_dma_ch_desc_t *dma_ch_info = (csi_dma_ch_desc_t *)ch_info; + + if (parent_dev == NULL) { + /* the MEM2MEM mode */ + for (ctrl_id = 0U; ctrl_id < ctrl_num; ctrl_id++) { + for (ch_id = 0U; ch_id < list[ctrl_id]->ch_num; ch_id++) { + if (!(list[ctrl_id]->alloc_status & ((uint32_t)1 << ch_id))) { + dma_ch_info->ch_idx = (uint8_t)ch_id; + dma_ch_info->ctrl_idx = (uint8_t)ctrl_id; + /* find the channel */ + is_find = 1; + break; + } + } + + if (is_find) { + break; + } + } + + if (is_find == 0) { + csi_ret = CSI_ERROR; + } + } else { + /* the MEM2PERH mode or PERH2MEM mode */ + for (spt_id = 0U; dma_spt_list[spt_id].dev_tag != 0xFFFFU; spt_id++) { + if ((dma_spt_list[spt_id].dev_tag == parent_dev->dev_tag) && ((uint8_t)dma_spt_list[spt_id].ctrl_idx == parent_dev->idx)) { + break; + } + } + + if (dma_spt_list[spt_id].dev_tag == 0xFFFFU) { + csi_ret = CSI_ERROR; + } + + for (ch_info_id = 0U;; ch_info_id++) { + if (dma_spt_list[spt_id].ch_list[ch_info_id].ctrl_idx == 0xFFU) { + csi_ret = CSI_ERROR; + break; + } + + for (ctrl_id = 0U; ctrl_id < ctrl_num; ctrl_id++) { + if ((ctrl_id == dma_spt_list[spt_id].ch_list[ch_info_id].ctrl_idx) && + !(list[ctrl_id]->alloc_status & ((uint32_t)1 << dma_spt_list[spt_id].ch_list[ch_info_id].ch_idx))) { + dma_ch_info->ch_idx = dma_spt_list[spt_id].ch_list[ch_info_id].ch_idx; + dma_ch_info->ctrl_idx = dma_spt_list[spt_id].ch_list[ch_info_id].ctrl_idx; + /* find the channel */ + is_find = 1; + break; + } + } + + if (is_find) { + break; + } + } + } + + return csi_ret; +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/tick.c b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/tick.c new file mode 100644 index 00000000000..a5ac75b6b09 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/chip_riscv_dummy/src/sys/tick.c @@ -0,0 +1,193 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __WEAK __attribute__((weak)) + +#if defined(CONFIG_SMP) && CONFIG_SMP +static volatile uint32_t csi_tick[CONFIG_NR_CPUS] = {0U}; +#else +static volatile uint32_t csi_tick = 0U; +#endif +static volatile uint32_t last_time_ms = 0U; +static volatile uint64_t last_time_us = 0U; +static volatile uint64_t timer_init_value = 0U; + +#if CONFIG_CPU_XUANTIE_E9XX || CONFIG_INTC_CLIC_PLIC +static csi_dev_t tick_dev; +#endif + +void csi_tick_increase(void) +{ +#if defined(CONFIG_SMP) && CONFIG_SMP + csi_tick[csi_get_cpu_id()]++; +#else + csi_tick++; +#endif +} + +uint32_t csi_tick_get(void) +{ +#if defined(CONFIG_SMP) && CONFIG_SMP + return csi_tick[csi_get_cpu_id()]; +#else + return csi_tick; +#endif +} + +void tick_irq_handler(void *arg) +{ + csi_tick_increase(); + csi_coret_config((soc_get_coretim_freq() / RT_TICK_PER_SECOND), CORET_IRQn); +#if CONFIG_AOS_OSAL + extern void aos_sys_tick_handler(void); + aos_sys_tick_handler(); +#else +#ifdef CONFIG_KERNEL_FREERTOS + extern void xPortSysTickHandler(void); + xPortSysTickHandler(); +#elif defined(CONFIG_KERNEL_RTTHREAD) + rt_interrupt_enter(); + extern void rt_tick_increase(void); + rt_tick_increase(); + rt_interrupt_leave(); +#else +#endif +#endif /* end CONFIG_AOS_OSAL */ +} + +csi_error_t csi_tick_init(void) +{ +#if CONFIG_CPU_XUANTIE_E9XX || CONFIG_INTC_CLIC_PLIC + tick_dev.irq_num = CORET_IRQn; + csi_vic_set_prio(tick_dev.irq_num, 31U); + csi_irq_attach(tick_dev.irq_num, &tick_irq_handler, &tick_dev); +#endif + +#if defined(CONFIG_SMP) && CONFIG_SMP + csi_tick[csi_get_cpu_id()] = 0; +#else + csi_tick = 0U; +#endif + timer_init_value = csi_coret_get_value2(); + csi_coret_reset_value2(); + csi_coret_config((soc_get_coretim_freq() / RT_TICK_PER_SECOND), CORET_IRQn); + csi_coret_irq_enable(); + + return CSI_OK; +} + +void csi_tick_uninit(void) +{ + csi_coret_irq_disable(); +#if CONFIG_CPU_XUANTIE_E9XX || CONFIG_INTC_CLIC_PLIC + csi_irq_detach(tick_dev.irq_num); +#endif +} + +uint32_t csi_tick_get_ms(void) +{ + uint32_t time; + + time = (uint32_t)((csi_coret_get_value2() - timer_init_value) * 1000U / (uint64_t)soc_get_coretim_freq()); + last_time_ms = time; + return time; +} + +uint64_t csi_tick_get_us(void) +{ + uint64_t time; + + time = (csi_coret_get_value2() - timer_init_value) * 1000U * 1000U / (uint64_t)soc_get_coretim_freq(); + last_time_us = time; + return time; +} + +static void _mdelay(void) +{ + uint64_t start = csi_coret_get_value2(); + uint64_t cur; + uint32_t cnt = (soc_get_coretim_freq() / 1000U); + + while (1) { + cur = csi_coret_get_value2(); + + if (start > cur) { + if ((start - cur) >= cnt) { + break; + } + } else { + if (cur - start >= cnt) { + break; + } + } + } +} + +static void _10udelay(void) +{ + uint64_t cur; + uint64_t start = csi_coret_get_value2(); + uint32_t cnt = (soc_get_coretim_freq() / 1000U / 100U); + + while (1) { + cur = csi_coret_get_value2(); + + if (start > cur) { + if ((start - cur) >= cnt) { + break; + } + } else { + if (cur - start >= cnt) { + break; + } + } + } +} + +__WEAK void mdelay(uint32_t ms) +{ + while (ms) { + ms--; + _mdelay(); + } +} + +/** + * Ps: At least delay over 10us +*/ +void udelay(uint32_t us) +{ + us /= 10U; + + while (us) { + us--; + _10udelay(); + } +} + diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/README.md b/bsp/xuantie/libraries/xuantie_libraries/csi/README.md new file mode 100644 index 00000000000..9e30ec0ae2a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/README.md @@ -0,0 +1,21 @@ +## 概述 + +CSI 是针对嵌入式系统,定义了CPU内核移植 接口、外围设备操作接口统一软件接口规范,消除不同芯片的差异,简化软件的使用及提高软件的移植性。通过CSI 接口规范,可以快>速实现芯片对接到YoC 平台。 + +CSI 的具体内容包括: + +- **CSI-CORE**:定义了CPU和相关紧耦合外设的接口规范 +- **CSI-DRIVER**:定义了常用的驱动的接口规范 +- **CSI-KERNEL**: 定义实时操作系统的接口规范 + + +## 组件安装 + +```bash +yoc init +yoc install csi +``` + +## 接口 + +[CSI接口描述](https://www.xrvm.cn/document?temp=csi&slug=csi-chn) diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/SConscript b/bsp/xuantie/libraries/xuantie_libraries/csi/SConscript new file mode 100644 index 00000000000..20f7689c53c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/SConscript b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/SConscript new file mode 100644 index 00000000000..f2c782be6cd --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/SConscript @@ -0,0 +1,15 @@ +from building import * +import os + +cwd = GetCurrentDir() + +CPPPATH = [cwd] +CPPPATH += [cwd + '/include'] +CPPPATH += [cwd + '/include/core'] +CPPPATH += [cwd + '/include/drv'] + +src = Split(""" +""") + +group = DefineGroup('csi2_inc', src, depend = [''], CPPPATH = CPPPATH) +Return('group') diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/README.txt b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/README.txt new file mode 100644 index 00000000000..bb1bf4a3def --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/README.txt @@ -0,0 +1 @@ +Just include csi_core.h! diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/core_rv32.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/core_rv32.h new file mode 100644 index 00000000000..17920e1dd74 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/core_rv32.h @@ -0,0 +1,1451 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + + +/****************************************************************************** + * @file core_rv32.h + * @brief CSI RV32 Core Peripheral Access Layer Header File + * @version V1.0 + * @date 01. Sep 2018 + ******************************************************************************/ + +#ifndef __CORE_RV32_H_GENERIC +#define __CORE_RV32_H_GENERIC + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * CSI definitions + ******************************************************************************/ +/** + \ingroup RV32 + @{ + */ + +#ifndef __RV32 +#define __RV32 (0x01U) +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __GNUC__ ) +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_RV32_H_GENERIC */ + +#ifndef __CSI_GENERIC + +#ifndef __CORE_RV32_H_DEPENDANT +#define __CORE_RV32_H_DEPENDANT + +#ifdef __cplusplus +extern "C" { +#endif + +/* check device defines and use defaults */ +#ifndef __RV32_REV +#define __RV32_REV 0x0000U +#endif + +#ifndef __VIC_PRIO_BITS +#define __VIC_PRIO_BITS 2U +#endif + +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 1U +#endif + +#ifndef __MPU_PRESENT +#define __MPU_PRESENT 1U +#endif + +#ifndef __ICACHE_PRESENT +#define __ICACHE_PRESENT 1U +#endif + +#ifndef __DCACHE_PRESENT +#define __DCACHE_PRESENT 1U +#endif + +#include + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CSI_glob_defs CSI Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus +#define __I volatile /*!< Defines 'read only' permissions */ +#else +#define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group RV32 */ + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core CLIC Register + ******************************************************************************/ +/** + \defgroup CSI_core_register Defines and Type Definitions + \brief Type definitions and defines for CK80X processor based devices. +*/ + +/** + \ingroup CSI_core_register + \defgroup CSI_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \ingroup CSI_core_register + \defgroup CSI_CLIC Core-Local Interrupt Controller (CLIC) + \brief Type definitions for the CLIC Registers + @{ + */ + +/** + \brief Access to the structure of a vector interrupt controller. + */ +typedef struct { + __IOM uint8_t IP; /*!< Offset: 0x000 (R/W) Interrupt set pending register */ + __IOM uint8_t IE; /*!< Offset: 0x004 (R/W) Interrupt set enable register */ + __IOM uint8_t ATTR; /*!< Offset: 0x008 (R/W) Interrupt set attribute register */ + __IOM uint8_t CTL; /*!< Offset: 0x00C (R/W) Interrupt control register */ +} CLIC_INT_Control; + +typedef struct { + __IOM uint32_t CLICCFG:8; /*!< Offset: 0x000 (R/W) CLIC configure register */ + __IM uint32_t CLICINFO; + __IOM uint32_t MINTTHRESH; + uint32_t RESERVED[1021]; + CLIC_INT_Control CLICINT[4096]; +} CLIC_Type; + +#define CLIC_INFO_CLICINTCTLBITS_Pos 21U +#define CLIC_INFO_CLICINTCTLBITS_Msk (0xFUL << CLIC_INFO_CLICINTCTLBITS_Pos) + +#define CLIC_INTIP_IP_Pos 0U /*!< CLIC INTIP: IP Position */ +#define CLIC_INTIP_IP_Msk (0x1UL << CLIC_INTIP_IP_Pos) /*!< CLIC INTIP: IP Mask */ + +#define CLIC_INTIE_IE_Pos 0U /*!< CLIC INTIE: IE Position */ +#define CLIC_INTIE_IE_Msk (0x1UL << CLIC_INTIE_IE_Pos) /*!< CLIC INTIE: IE Mask */ + +#define CLIC_INTIE_T_Pos 7U /*!< CLIC INTIE: T Position */ +#define CLIC_INTIE_T_Msk (0x1UL << CLIC_INTIE_T_Pos) /*!< CLIC INTIE: T Mask */ + +#define CLIC_INTATTR_TRIG_Pos 1U /*!< CLIC INTATTR: TRIG Position */ +#define CLIC_INTATTR_TRIG_Msk (0x3UL << CLIC_INTATTR_TRIG_Pos) /*!< CLIC INTATTR: TRIG Mask */ + +#define CLIC_INTATTR_SHV_Pos 0U /*!< CLIC INTATTR: SHV Position */ +#define CLIC_INTATTR_SHV_Msk (0x1UL << CLIC_INTATTR_SHV_Pos) /*!< CLIC INTATTR: SHV Mask */ + +#define CLIC_INTCFG_NVBIT_Pos 5U /*!< CLIC INTCFG: NVBIT Position */ +#define CLIC_INTCFG_NVBIT_Msk (0x1UL << CLIC_INTCFG_NVBIT_Pos) /*!< CLIC INTCFG: NVBIT Mask */ + +#define CLIC_INTCFG_PRIO_Pos 5U /*!< CLIC INTCFG: INTCFG Position */ +#define CLIC_INTCFG_PRIO_Msk (0x7UL << CLIC_INTCFG_PRIO_Pos) /*!< CLIC INTCFG: INTCFG Mask */ + +#define CLIC_CLICCFG_NVBIT_Pos 0U /*!< CLIC CLICCFG: NVBIT Position */ +#define CLIC_CLICCFG_NVBIT_Msk (0x1UL << CLIC_CLICCFG_NVBIT_Pos) /*!< CLIC CLICCFG: NVBIT Mask */ + +#define CLIC_CLICCFG_NLBIT_Pos 1U /*!< CLIC CLICCFG: NLBIT Position */ +#define CLIC_CLICCFG_NLBIT_Msk (0xFUL << CLIC_CLICCFG_NLBIT_Pos) /*!< CLIC CLICCFG: NLBIT Mask */ + +#define CLIC_CLICCFG_NMBIT_Pos 5U /*!< CLIC CLICCFG: NMBIT Position */ +#define CLIC_CLICCFG_NMBIT_Msk (0x3UL << CLIC_CLICCFG_NMBIT_Pos) /*!< CLIC CLICCFG: NMBIT Mask */ + +/*@} end of group CSI_CLIC */ + +/** + \ingroup CSI_core_register + \defgroup CSI_PMP Physical Memory Protection (PMP) + \brief Type definitions for the PMP Registers + @{ + */ + +#define PMP_PMPCFG_R_Pos 0U /*!< PMP PMPCFG: R Position */ +#define PMP_PMPCFG_R_Msk (0x1UL << PMP_PMPCFG_R_Pos) /*!< PMP PMPCFG: R Mask */ + +#define PMP_PMPCFG_W_Pos 1U /*!< PMP PMPCFG: W Position */ +#define PMP_PMPCFG_W_Msk (0x1UL << PMP_PMPCFG_W_Pos) /*!< PMP PMPCFG: W Mask */ + +#define PMP_PMPCFG_X_Pos 2U /*!< PMP PMPCFG: X Position */ +#define PMP_PMPCFG_X_Msk (0x1UL << PMP_PMPCFG_X_Pos) /*!< PMP PMPCFG: X Mask */ + +#define PMP_PMPCFG_A_Pos 3U /*!< PMP PMPCFG: A Position */ +#define PMP_PMPCFG_A_Msk (0x3UL << PMP_PMPCFG_A_Pos) /*!< PMP PMPCFG: A Mask */ + +#define PMP_PMPCFG_L_Pos 7U /*!< PMP PMPCFG: L Position */ +#define PMP_PMPCFG_L_Msk (0x1UL << PMP_PMPCFG_L_Pos) /*!< PMP PMPCFG: L Mask */ + +typedef enum { + REGION_SIZE_4B = -1, + REGION_SIZE_8B = 0, + REGION_SIZE_16B = 1, + REGION_SIZE_32B = 2, + REGION_SIZE_64B = 3, + REGION_SIZE_128B = 4, + REGION_SIZE_256B = 5, + REGION_SIZE_512B = 6, + REGION_SIZE_1KB = 7, + REGION_SIZE_2KB = 8, + REGION_SIZE_4KB = 9, + REGION_SIZE_8KB = 10, + REGION_SIZE_16KB = 11, + REGION_SIZE_32KB = 12, + REGION_SIZE_64KB = 13, + REGION_SIZE_128KB = 14, + REGION_SIZE_256KB = 15, + REGION_SIZE_512KB = 16, + REGION_SIZE_1MB = 17, + REGION_SIZE_2MB = 18, + REGION_SIZE_4MB = 19, + REGION_SIZE_8MB = 20, + REGION_SIZE_16MB = 21, + REGION_SIZE_32MB = 22, + REGION_SIZE_64MB = 23, + REGION_SIZE_128MB = 24, + REGION_SIZE_256MB = 25, + REGION_SIZE_512MB = 26, + REGION_SIZE_1GB = 27, + REGION_SIZE_2GB = 28, + REGION_SIZE_4GB = 29, + REGION_SIZE_8GB = 30, + REGION_SIZE_16GB = 31 +} region_size_e; + +typedef enum { + ADDRESS_MATCHING_TOR = 1, + ADDRESS_MATCHING_NAPOT = 3 +} address_matching_e; + +typedef struct { + uint32_t r: 1; /* readable enable */ + uint32_t w: 1; /* writeable enable */ + uint32_t x: 1; /* execable enable */ + address_matching_e a: 2; /* address matching mode */ + uint32_t reserved: 2; /* reserved */ + uint32_t l: 1; /* lock enable */ +} mpu_region_attr_t; + +/*@} end of group CSI_PMP */ + +/* CACHE Register Definitions */ +#define CACHE_MHCR_BTB_Pos 12U /*!< CACHE MHCR: BTB Position */ +#define CACHE_MHCR_BTB_Msk (0x1UL << CACHE_MHCR_BTB_Pos) /*!< CACHE MHCR: WA Mask */ + +#define CACHE_MHCR_BPE_Pos 5U /*!< CACHE MHCR: BPE Position */ +#define CACHE_MHCR_BPE_Msk (0x1UL << CACHE_MHCR_BPE_Pos) /*!< CACHE MHCR: BPE Mask */ + +#define CACHE_MHCR_RS_Pos 4U /*!< CACHE MHCR: RS Position */ +#define CACHE_MHCR_RS_Msk (0x1UL << CACHE_MHCR_RS_Pos) /*!< CACHE MHCR: RS Mask */ + +#define CACHE_MHCR_WA_Pos 3U /*!< CACHE MHCR: WA Position */ +#define CACHE_MHCR_WA_Msk (0x1UL << CACHE_MHCR_WA_Pos) /*!< CACHE MHCR: WA Mask */ + +#define CACHE_MHCR_WB_Pos 2U /*!< CACHE MHCR: WB Position */ +#define CACHE_MHCR_WB_Msk (0x1UL << CACHE_MHCR_WB_Pos) /*!< CACHE MHCR: WB Mask */ + +#define CACHE_MHCR_DE_Pos 1U /*!< CACHE MHCR: DE Position */ +#define CACHE_MHCR_DE_Msk (0x1UL << CACHE_MHCR_DE_Pos) /*!< CACHE MHCR: DE Mask */ + +#define CACHE_MHCR_IE_Pos 0U /*!< CACHE MHCR: IE Position */ +#define CACHE_MHCR_IE_Msk (0x1UL << CACHE_MHCR_IE_Pos) /*!< CACHE MHCR: IE Mask */ + +#define CACHE_INV_ADDR_Pos 5U +#define CACHE_INV_ADDR_Msk (0xFFFFFFFFUL << CACHE_INV_ADDR_Pos) + +/*@} end of group CSI_CACHE */ + +/** + \ingroup CSI_core_register + \defgroup CSI_SYSMAP system map (SYSMAP) + \brief Type definitions for the SYSMAP Registers + @{ + */ + +#define SYSMAP_SYSMAPCFG_B_Pos 0U /*!< SYSMAP SYSMAPCFG: B Position */ +#define SYSMAP_SYSMAPCFG_B_Msk (0x1UL << SYSMAP_SYSMAPCFG_B_Pos) /*!< SYSMAP SYSMAPCFG: B Mask */ + +#define SYSMAP_SYSMAPCFG_C_Pos 1U /*!< SYSMAP SYSMAPCFG: C Position */ +#define SYSMAP_SYSMAPCFG_C_Msk (0x1UL << SYSMAP_SYSMAPCFG_C_Pos) /*!< SYSMAP SYSMAPCFG: C Mask */ + +#define SYSMAP_SYSMAPCFG_SO_Pos 2U /*!< SYSMAP SYSMAPCFG: SO Position */ +#define SYSMAP_SYSMAPCFG_SO_Msk (0x1UL << SYSMAP_SYSMAPCFG_SO_Pos) /*!< SYSMAP SYSMAPCFG: SO Mask */ + +/** + \ingroup CSI_core_register + \defgroup CSI_SYSMAP system map (SYSMAP) + \brief Type definitions for the SYSMAP Registers + @{ + */ +typedef struct { + __IOM uint32_t SYSMAPADDR0; /*!< Offset: 0x000 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPCFG0; /*!< Offset: 0x004 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPADDR1; /*!< Offset: 0x008 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPCFG1; /*!< Offset: 0x00c (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPADDR2; /*!< Offset: 0x010 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPCFG2; /*!< Offset: 0x014 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPADDR3; /*!< Offset: 0x018 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPCFG3; /*!< Offset: 0x01c (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPADDR4; /*!< Offset: 0x020 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPCFG4; /*!< Offset: 0x024 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPADDR5; /*!< Offset: 0x028 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPCFG5; /*!< Offset: 0x02c (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPADDR6; /*!< Offset: 0x030 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPCFG6; /*!< Offset: 0x034 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPADDR7; /*!< Offset: 0x038 (R/W) SYSMAP configure register */ + __IOM uint32_t SYSMAPCFG7; /*!< Offset: 0x03c (R/W) SYSMAP configure register */ +} SYSMAP_Type; + + +/*@} end of group CSI_SYSMAP */ + + +/** + \ingroup CSI_core_register + \defgroup CSI_SysTick System Tick Timer (CORET) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief The data structure of the access system timer. + */ +typedef struct { + __IOM unsigned long long MTIMECMP; /*!< Offset: 0x000 (R/W) Timer compare register */ + uint32_t RESERVED[8188]; + __IM unsigned long long MTIME; /*!< Offset: 0x7FF8 (R) Timer current register */ +} CORET_Type; + +/*@} end of group CSI_SysTick */ + +/** + \ingroup CSI_core_register + \defgroup CSI_DCC + \brief Type definitions for the DCC. + @{ + */ + +/** + \brief Access to the data structure of DCC. + */ +typedef struct { + uint32_t RESERVED0[13U]; + __IOM uint32_t HCR; /*!< Offset: 0x034 (R/W) */ + __IM uint32_t EHSR; /*!< Offset: 0x03C (R/ ) */ + uint32_t RESERVED1[6U]; + union { + __IM uint32_t DERJW; /*!< Offset: 0x058 (R/ ) Data exchange register CPU read*/ + __OM uint32_t DERJR; /*!< Offset: 0x058 ( /W) Data exchange register CPU writer*/ + }; + +} DCC_Type; + +#define DCC_HCR_JW_Pos 18U /*!< DCC HCR: jw_int_en Position */ +#define DCC_HCR_JW_Msk (1UL << DCC_HCR_JW_Pos) /*!< DCC HCR: jw_int_en Mask */ + +#define DCC_HCR_JR_Pos 19U /*!< DCC HCR: jr_int_en Position */ +#define DCC_HCR_JR_Msk (1UL << DCC_HCR_JR_Pos) /*!< DCC HCR: jr_int_en Mask */ + +#define DCC_EHSR_JW_Pos 1U /*!< DCC EHSR: jw_vld Position */ +#define DCC_EHSR_JW_Msk (1UL << DCC_EHSR_JW_Pos) /*!< DCC EHSR: jw_vld Mask */ + +#define DCC_EHSR_JR_Pos 2U /*!< DCC EHSR: jr_vld Position */ +#define DCC_EHSR_JR_Msk (1UL << DCC_EHSR_JR_Pos) /*!< DCC EHSR: jr_vld Mask */ + +/*@} end of group CSI_DCC */ + + +/** + \ingroup CSI_core_register + \defgroup CSI_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CSI_core_bitfield */ + +/** + \ingroup CSI_core_register + \defgroup CSI_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of THEAD CPU */ +#define CORET_BASE (0xE0004000UL) /*!< CORET Base Address */ +#define CLIC_BASE (0xE0800000UL) /*!< CLIC Base Address */ +#define SYSMAP_BASE (0xEFFFF000UL) /*!< SYSMAP Base Address */ + +#define CORET ((CORET_Type *) CORET_BASE ) /*!< SysTick configuration struct */ +#define CLIC ((CLIC_Type *) CLIC_BASE ) /*!< CLIC configuration struct */ +#define SYSMAP ((SYSMAP_Type *) SYSMAP_BASE ) /*!< SYSMAP configuration struct */ + +/*@} */ + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core VIC Functions + - Core CORET Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CSI_Core_FunctionInterface Functions and Instructions Reference +*/ + +/** + \brief Get current hartid + \return hartid + */ +__STATIC_INLINE int csi_get_cpu_id(void) +{ + unsigned long result; + __ASM volatile("csrr %0, mhartid" : "=r"(result) : : "memory"); + return result; +} + +/** + \brief Get cache line size + \return cache line size + */ +__STATIC_INLINE int csi_get_cache_line_size(void) +{ +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP + return 8; +#else + return 4; +#endif +} + +/* ########################## VIC functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_VICFunctions VIC Functions + \brief Functions that manage interrupts and exceptions via the VIC. + @{ + */ + +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 5UL) ) +#define _IP2_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +/** + \brief Enable External Interrupt + \details Enable a device-specific interrupt in the VIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_enable_irq(int32_t IRQn) +{ + CLIC->CLICINT[IRQn].IE |= CLIC_INTIE_IE_Msk; + __DSB(); +} + +/** + \brief Disable External Interrupt + \details Disable a device-specific interrupt in the VIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_disable_irq(int32_t IRQn) +{ + CLIC->CLICINT[IRQn].IE &= ~CLIC_INTIE_IE_Msk; + __DSB(); +} + +/** + \brief Check Interrupt is Enabled or not + \details Read the enabled register in the VIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not enabled. + \return 1 Interrupt status is enabled. + */ +__STATIC_INLINE uint32_t csi_vic_get_enabled_irq(int32_t IRQn) +{ + return (uint32_t)(CLIC->CLICINT[IRQn].IE & CLIC_INTIE_IE_Msk); +} + +/** + \brief Check Interrupt is Pending or not + \details Read the pending register in the VIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t csi_vic_get_pending_irq(int32_t IRQn) +{ + return (uint32_t)(CLIC->CLICINT[IRQn].IP & CLIC_INTIP_IP_Msk); +} + +/** + \brief Set Pending Interrupt + \details Set the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_set_pending_irq(int32_t IRQn) +{ + CLIC->CLICINT[IRQn].IP |= CLIC_INTIP_IP_Msk; +} + +/** + \brief Clear Pending Interrupt + \details Clear the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_clear_pending_irq(int32_t IRQn) +{ + CLIC->CLICINT[IRQn].IP &= ~CLIC_INTIP_IP_Msk; +} + +/** + \brief Set Interrupt Priority + \details Set the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void csi_vic_set_prio(int32_t IRQn, uint32_t priority) +{ + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + CLIC->CLICINT[IRQn].CTL = (CLIC->CLICINT[IRQn].CTL & (~CLIC_INTCFG_PRIO_Msk)) | (priority << (8 - nlbits)); + __DSB(); +} + +/** + \brief Get Interrupt Priority + \details Read the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t csi_vic_get_prio(int32_t IRQn) +{ + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + return CLIC->CLICINT[IRQn].CTL >> (8 - nlbits); +} + +/** + \brief Get Interrupt thresh + \details Read the thresh of interrupt + Only the interrupt priority is greater than the value of thresh, the interrupt can be responded to + \return Interrupt thresh value(0~255). + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t csi_vic_get_thresh(void) +{ + return CLIC->MINTTHRESH >> 24; +} + +/** + \brief Set Interrupt thresh + \details Write the thresh of interrupt + Only the interrupt priority is greater than the value of thresh, the interrupt can be responded to + \param [in] Interrupt thresh value(0~255). + */ +__STATIC_INLINE uint32_t csi_vic_set_thresh(uint32_t thresh) +{ + uint32_t temp = CLIC->MINTTHRESH; + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + + if(!nlbits) + CLIC->MINTTHRESH = 0xff << 24; + + CLIC->MINTTHRESH = thresh << 24; + return temp; +} + +/*@} end of CSI_Core_VICFunctions */ + +/* ########################## PMP functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_PMPFunctions PMP Functions + \brief Functions that manage interrupts and exceptions via the VIC. + @{ + */ + +/** + \brief configure memory protected region. + \details + \param [in] idx memory protected region (0, 1, 2, ..., 15). + \param [in] base_addr base address must be aligned with page size. + \param [in] size \ref region_size_e. memory protected region size. + \param [in] attr \ref region_size_t. memory protected region attribute. + \param [in] enable enable or disable memory protected region. + */ +__STATIC_INLINE void csi_mpu_config_region(uint32_t idx, uint32_t base_addr, region_size_e size, + mpu_region_attr_t attr, uint32_t enable) +{ + uint8_t pmpxcfg = 0; + uint32_t addr = 0; + + if (idx > 15) { + return; + } + + if (!enable) { + attr.a = (address_matching_e)0; + } + + if (attr.a == ADDRESS_MATCHING_TOR) { + addr = base_addr >> 2; + } else { + if (size == REGION_SIZE_4B) { + addr = base_addr >> 2; + attr.a = (address_matching_e)2; + } else { + addr = ((base_addr >> 2) & (0xFFFFFFFFU - ((1 << (size + 1)) - 1))) | ((1 << size) - 1); + } + } + + __set_PMPADDRx(idx, addr); + + pmpxcfg |= (attr.r << PMP_PMPCFG_R_Pos) | (attr.w << PMP_PMPCFG_W_Pos) | + (attr.x << PMP_PMPCFG_X_Pos) | (attr.a << PMP_PMPCFG_A_Pos) | + (attr.l << PMP_PMPCFG_L_Pos); + + __set_PMPxCFG(idx, pmpxcfg); +} + +/** + \brief disable mpu region by idx. + \details + \param [in] idx memory protected region (0, 1, 2, ..., 15). + */ +__STATIC_INLINE void csi_mpu_disable_region(uint32_t idx) +{ + __set_PMPxCFG(idx, __get_PMPxCFG(idx) & (~PMP_PMPCFG_A_Msk)); +} + +/*@} end of CSI_Core_PMPFunctions */ + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +__STATIC_INLINE uint32_t _csi_coret_config(unsigned long coret_base, uint32_t ticks, int32_t IRQn) +{ + CORET_Type *coret = (CORET_Type *)coret_base; + if ((coret->MTIMECMP != 0) && (coret->MTIMECMP != 0xffffffffffffffff)) { + coret->MTIMECMP = coret->MTIMECMP + ticks; + } else { + coret->MTIMECMP = coret->MTIME + ticks; + } + return (0UL); +} + +/** + \brief CORE timer Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \param [in] IRQn core timer Interrupt number. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t csi_coret_config(uint32_t ticks, int32_t IRQn) +{ + return _csi_coret_config(CORET_BASE, ticks, IRQn); +} + +/** + \brief get CORE timer reload value + \return CORE timer counter value(64bit). + */ +__STATIC_INLINE uint64_t csi_coret_get_load2(void) +{ + return CORET->MTIMECMP; +} + +/** + \brief get CORE timer reload value(deprecated) + \return CORE timer counter value. + */ +__STATIC_INLINE unsigned long csi_coret_get_load(void) +{ + return CORET->MTIMECMP & 0xFFFFFFFF; +} + +/** + \brief get CORE timer reload high value(deprecated) + \return CORE timer counter value. + */ +__STATIC_INLINE uint32_t csi_coret_get_loadh(void) +{ + return (CORET->MTIMECMP >> 32) & 0xFFFFFFFF; +} + +/** + \brief get CORE timer counter value + \return CORE timer counter value(64bit). + */ +__STATIC_INLINE uint64_t csi_coret_get_value2(void) +{ + return CORET->MTIME; +} + +/** + \brief get CORE timer counter value(deprecated) + \return CORE timer counter value. + */ +__STATIC_INLINE unsigned long csi_coret_get_value(void) +{ + return CORET->MTIME & 0xFFFFFFFF; +} + +/** + \brief get CORE timer counter high value(deprecated) + \return CORE timer counter value. + */ +__STATIC_INLINE uint32_t csi_coret_get_valueh(void) +{ + return (CORET->MTIME >> 32) & 0xFFFFFFFF; +} + +__STATIC_INLINE void csi_coret_reset_value2() +{ + CORET_Type *coret = (CORET_Type *)CORET_BASE; + coret->MTIMECMP = 0; +} + +/** + \brief Enable CoreTimer(within clint) Interrupts + */ +__ALWAYS_STATIC_INLINE void csi_coret_irq_enable(void) +{ + extern void soc_irq_enable(uint32_t irq_num); + return soc_irq_enable(7); +} + +/** + \brief Disable CoreTimer(within clint) Interrupts + */ +__ALWAYS_STATIC_INLINE void csi_coret_irq_disable(void) +{ + extern void soc_irq_disable(uint32_t irq_num); + return soc_irq_disable(7); +} + +/*@} end of CSI_Core_SysTickFunctions */ + +/* ########################## SYSMAP functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_SYSMAPFunctions SYSMAP Functions + \brief Functions that manage system map attribute + @{ + */ + +/** + \brief Get SYSMAPCFGx Register by index + \details Returns the content of the SYSMAPxCFG Register. + \param [in] idx SYSMAP region index + \return SYSMAPxCFG Register value + */ +__STATIC_INLINE uint8_t __get_SYSMAPCFGx(uint32_t idx) +{ + switch (idx) { + case 0: + return SYSMAP->SYSMAPCFG0; + case 1: + return SYSMAP->SYSMAPCFG1; + case 2: + return SYSMAP->SYSMAPCFG2; + case 3: + return SYSMAP->SYSMAPCFG3; + case 4: + return SYSMAP->SYSMAPCFG4; + case 5: + return SYSMAP->SYSMAPCFG5; + case 6: + return SYSMAP->SYSMAPCFG6; + case 7: + return SYSMAP->SYSMAPCFG7; + default: + return 0; + } +} + +/** + \brief Set SYSMAPCFGx by index + \details Writes the given value to the SYSMAPxCFG Register. + \param [in] idx SYSMAPx region index + \param [in] sysmapxcfg SYSMAPxCFG Register value to set + */ +__STATIC_INLINE void __set_SYSMAPCFGx(uint32_t idx, uint32_t sysmapxcfg) +{ + switch (idx) { + case 0: + SYSMAP->SYSMAPCFG0 = sysmapxcfg; + break; + case 1: + SYSMAP->SYSMAPCFG1 = sysmapxcfg; + break; + case 2: + SYSMAP->SYSMAPCFG2 = sysmapxcfg; + break; + case 3: + SYSMAP->SYSMAPCFG3 = sysmapxcfg; + break; + case 4: + SYSMAP->SYSMAPCFG4 = sysmapxcfg; + break; + case 5: + SYSMAP->SYSMAPCFG5 = sysmapxcfg; + break; + case 6: + SYSMAP->SYSMAPCFG6 = sysmapxcfg; + break; + case 7: + SYSMAP->SYSMAPCFG7 = sysmapxcfg; + break; + default: + return; + } +} + +/** + \brief Get SYSMAPADDRx Register by index + \details Returns the content of the SYSMAPADDRx Register. + \param [in] idx SYSMAP region index + \return SYSMAPADDRx Register value + */ +__STATIC_INLINE uint32_t __get_SYSMAPADDRx(uint32_t idx) +{ + switch(idx) { + case 0: + return SYSMAP->SYSMAPADDR0; + case 1: + return SYSMAP->SYSMAPADDR1; + case 2: + return SYSMAP->SYSMAPADDR2; + case 3: + return SYSMAP->SYSMAPADDR3; + case 4: + return SYSMAP->SYSMAPADDR4; + case 5: + return SYSMAP->SYSMAPADDR5; + case 6: + return SYSMAP->SYSMAPADDR6; + case 7: + return SYSMAP->SYSMAPADDR7; + default: + return 0; + } +} + +/** + \brief Set SYSMAPADDRx by index + \details Writes the given value to the SYSMAPADDRx Register. + \param [in] idx SYSMAP region index + \param [in] sysmapaddr SYSMAPADDRx Register value to set + */ +__STATIC_INLINE void __set_SYSMAPADDRx(uint32_t idx, uint32_t sysmapxaddr) +{ + switch (idx) { + case 0: + SYSMAP->SYSMAPADDR0 = sysmapxaddr; + break; + case 1: + SYSMAP->SYSMAPADDR1 = sysmapxaddr; + break; + case 2: + SYSMAP->SYSMAPADDR2 = sysmapxaddr; + break; + case 3: + SYSMAP->SYSMAPADDR3 = sysmapxaddr; + break; + case 4: + SYSMAP->SYSMAPADDR4 = sysmapxaddr; + break; + case 5: + SYSMAP->SYSMAPADDR5 = sysmapxaddr; + break; + case 6: + SYSMAP->SYSMAPADDR6 = sysmapxaddr; + break; + case 7: + SYSMAP->SYSMAPADDR7 = sysmapxaddr; + break; + default: + return; + } +} + +/** + \brief configure system map attribute. + \details + \param [in] idx system map region (0, 1, 2, ..., 7). + \param [in] base_addr base address must be aligned with page size. + \param [in] enable enable or disable memory protected region. + */ +__STATIC_INLINE void csi_sysmap_config_region(uint32_t idx, uint32_t base_addr, uint32_t attr) +{ + uint32_t addr = 0; + + if (idx > 7) { + return; + } + + addr = base_addr >> 12; + attr = attr << 2; + + __set_SYSMAPADDRx(idx, addr); + __set_SYSMAPCFGx(idx, attr); +} + +/*@} end of CSI_Core_SYSMAPFunctions */ + +/* ########################## Cache functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_CacheFunctions Cache Functions + \brief Functions that configure Instruction and Data cache. + @{ + */ + +/** + \brief whether I-Cache enable + */ +__STATIC_INLINE int csi_icache_is_enable() +{ + uint32_t cache = __get_MHCR(); + return (cache & CACHE_MHCR_IE_Msk) >> CACHE_MHCR_IE_Pos; +} + +/** + \brief Enable I-Cache + \details Turns on I-Cache + */ +__STATIC_INLINE void csi_icache_enable (void) +{ +#if (__ICACHE_PRESENT == 1U) + if (!csi_icache_is_enable()) { + uint32_t cache; + __DSB(); + __ISB(); + __ICACHE_IALL(); + cache = __get_MHCR(); + cache |= CACHE_MHCR_IE_Msk; + __set_MHCR(cache); + __DSB(); + __ISB(); + } +#endif +} + + +/** + \brief Disable I-Cache + \details Turns off I-Cache + */ +__STATIC_INLINE void csi_icache_disable (void) +{ +#if (__ICACHE_PRESENT == 1U) + if (csi_icache_is_enable()) { + uint32_t cache; + __DSB(); + __ISB(); + cache = __get_MHCR(); + cache &= ~CACHE_MHCR_IE_Msk; /* disable icache */ + __set_MHCR(cache); + __ICACHE_IALL(); /* invalidate all icache */ + __DSB(); + __ISB(); + } +#endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_INLINE void csi_icache_invalid (void) +{ +#if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __ICACHE_IALL(); /* invalidate all icache */ + __DSB(); + __ISB(); +#endif +} + +/** + \brief whether D-Cache enable + */ +__STATIC_INLINE int csi_dcache_is_enable() +{ + uint32_t cache = __get_MHCR(); + return (cache & CACHE_MHCR_DE_Msk) >> CACHE_MHCR_DE_Pos; +} + +/** + \brief Enable D-Cache + \details Turns on D-Cache + */ +__STATIC_INLINE void csi_dcache_enable (void) +{ +#if (__DCACHE_PRESENT == 1U) + if (!csi_dcache_is_enable()) { + uint32_t cache; + __DSB(); + __ISB(); + __DCACHE_IALL(); /* invalidate all dcache */ + cache = __get_MHCR(); + cache |= CACHE_MHCR_DE_Msk; /* enable dcache */ + __set_MHCR(cache); + + __DSB(); + __ISB(); + } +#endif +} + + +/** + \brief Disable D-Cache + \details Turns off D-Cache + */ +__STATIC_INLINE void csi_dcache_disable (void) +{ +#if (__DCACHE_PRESENT == 1U) + if (csi_dcache_is_enable()) { + uint32_t cache; + __DSB(); + __ISB(); + cache = __get_MHCR(); + cache &= ~(uint32_t)CACHE_MHCR_DE_Msk; /* disable all Cache */ + __set_MHCR(cache); + __DCACHE_IALL(); /* invalidate all Cache */ + __DSB(); + __ISB(); + } +#endif +} + + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_INLINE void csi_dcache_invalid (void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __DCACHE_IALL(); /* invalidate all Cache */ + __DSB(); + __ISB(); +#endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_INLINE void csi_dcache_clean (void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __DCACHE_CALL(); /* clean all Cache */ + __DSB(); + __ISB(); +#endif +} + + +/** + \brief Clean & Invalidate D-Cache + \details Cleans and Invalidates D-Cache + */ +__STATIC_INLINE void csi_dcache_clean_invalid (void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __DCACHE_CIALL(); /* clean and inv all Cache */ + __DSB(); + __ISB(); +#endif +} + + +/** + \brief D-Cache Invalidate by address + \details Invalidates D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void csi_dcache_invalid_range (unsigned long *addr, size_t dsize) +{ +#if (__DCACHE_PRESENT == 1U) + int linesize = csi_get_cache_line_size(); + long op_size = dsize + (unsigned long)addr % linesize; + unsigned long op_addr = (unsigned long)addr; + + __DSB(); + + while (op_size > 0) { + __DCACHE_IPA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); +#endif +} + + +/** + \brief D-Cache Clean by address + \details Cleans D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void csi_dcache_clean_range (unsigned long *addr, size_t dsize) +{ + +#if (__DCACHE_PRESENT == 1U) + int linesize = csi_get_cache_line_size(); + long op_size = dsize + (unsigned long)addr % linesize; + unsigned long op_addr = (unsigned long) addr & CACHE_INV_ADDR_Msk; + + __DSB(); + + while (op_size > 0) { + __DCACHE_CPA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); +#endif + +} + + +/** + \brief D-Cache Clean and Invalidate by address + \details Cleans and invalidates D_Cache for the given address + \param[in] addr address (aligned to 16-byte boundary) + \param[in] dsize size of memory block (aligned to 16-byte boundary) +*/ +__STATIC_INLINE void csi_dcache_clean_invalid_range (unsigned long *addr, size_t dsize) +{ +#if (__DCACHE_PRESENT == 1U) + int linesize = csi_get_cache_line_size(); + long op_size = dsize + (unsigned long)addr % linesize; + unsigned long op_addr = (unsigned long) addr; + + __DSB(); + + while (op_size > 0) { + __DCACHE_CIPA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); +#endif +} + +/*@} end of CSI_Core_CacheFunctions */ + +#if (CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP) +/** + \ingroup CSI_tcm_register + \defgroup CSI_TCM + \brief Type definitions for the tcm Registers + @{ + */ + +/** + \brief Consortium definition for accessing protection area selection register(MITCMCR, csr<0x7f9>). + */ +typedef union { + struct { + uint32_t EN: 1; /*!< bit: 0 Instruction Tightly-Coupled Memory enable */ + uint32_t _reserved0: 1; /*!< bit: 1 Reserved */ + uint32_t _reserved1: 1; /*!< bit: 2 Reserved */ + uint32_t _reserved2: 1; /*!< bit: 3 Reserved */ + uint32_t Size: 4; /*!< bit: 4..7 Size of ITCM */ + uint32_t _reserved4: 4; /*!< bit: 8..11 Reserved */ + uint32_t Base_Address: 20; /*!< bit: 12..31 Base address of ITCM */ + } b; /*!< Structure Access by bit */ + uint32_t w; /*!< Type Access by whole register */ +} MITCMCR_Type; + +#define MITCMCR_Base_Address_Pos 12U /*!< MITCMCR: Base_Address Position */ +#define MITCMCR_Base_Address_Msk (0xfffffUL << MITCMCR_Base_Address_Pos) /*!< MITCMCR: Base_Address Mask */ + +#define MITCMCR_Size_Pos 4U /*!< MITCMCR: Size Position */ +#define MITCMCR_Size_Msk (0xfUL << MITCMCR_Size_Pos) /*!< MITCMCR: Size Mask */ + +#define MITCMCR_EN_Pos 0U /*!< MITCMCR: EN Position */ +#define MITCMCR_EN_Msk (0x1UL << MITCMCR_EN_Pos) /*!< MITCMCR: EN Mask */ + +/** + \brief Consortium definition for accessing protection area selection register(MDTCMCR, csr<0x7f8>). + */ +typedef union { + struct { + uint32_t EN: 1; /*!< bit: 0 Instruction Tightly-Coupled Memory enable */ + uint32_t _reserved0: 1; /*!< bit: 1 Reserved */ + uint32_t _reserved1: 1; /*!< bit: 2 Reserved */ + uint32_t _reserved2: 1; /*!< bit: 3 Reserved */ + uint32_t Size: 4; /*!< bit: 4..7 Size of DTCM */ + uint32_t _reserved4: 4; /*!< bit: 8..11 Reserved */ + uint32_t Base_Address: 20; /*!< bit: 12..31 Base address of DTCM */ + } b; /*!< Structure Access by bit */ + uint32_t w; /*!< Type Access by whole register */ +} MDTCMCR_Type; + +#define MDTCMCR_Base_Address_Pos 12U /*!< MDTCMCR: Base_Address Position */ +#define MDTCMCR_Base_Address_Msk (0xfffffUL << MDTCMCR_Base_Address_Pos) /*!< MDTCMCR: Base_Address Mask */ + +#define MDTCMCR_Size_Pos 4U /*!< MDTCMCR: Size Position */ +#define MDTCMCR_Size_Msk (0xfUL << MDTCMCR_Size_Pos) /*!< MDTCMCR: Size Mask */ + +#define MDTCMCR_EN_Pos 0U /*!< MDTCMCR: EN Position */ +#define MDTCMCR_EN_Msk (0x1UL << MDTCMCR_EN_Pos) /*!< MDTCMCR: EN Mask */ +/*@} end of group CSI_TCM_bitfield */ + +/* ########################## TCM functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_TCMFunctions TCM Functions + \brief Functions that configure TCM. + @{ + */ + +/** + \brief Enable ITCM + \details Turns on ITCM + */ +__STATIC_INLINE void csi_itcm_enable (void) +{ + __set_MITCMCR(__get_MITCMCR() | MITCMCR_EN_Msk); +} + +/** + \brief Enable DTCM + \details Turns on DTCM + */ +__STATIC_INLINE void csi_dtcm_enable (void) +{ + __set_MDTCMCR(__get_MDTCMCR() | MDTCMCR_EN_Msk); +} + +/** + \brief Enable ITCM + \details Turns on ITCM + */ +__STATIC_INLINE void csi_itcm_disable (void) +{ + __set_MITCMCR(__get_MITCMCR() & (~MITCMCR_EN_Msk)); +} + +/** + \brief Enable DTCM + \details Turns on DTCM + */ +__STATIC_INLINE void csi_dtcm_disable (void) +{ + __set_MDTCMCR(__get_MDTCMCR() & (~MDTCMCR_EN_Msk)); +} + +/** + \brief Get ITCM Size + \details Get ITCM Size + \return ITCM size (bytes). + */ +__STATIC_INLINE uint32_t csi_itcm_get_size(void) +{ + MITCMCR_Type sizemask; + uint32_t ret; + + sizemask.w = __get_MITCMCR(); + switch (sizemask.b.Size) + { + case 0x3: ret = 4 << 10; break; + case 0x4: ret = 8 << 10; break; + case 0x5: ret = 16 << 10; break; + case 0x6: ret = 32 << 10; break; + case 0x7: ret = 64 << 10; break; + case 0x8: ret = 128 << 10; break; + case 0x9: ret = 256 << 10; break; + case 0xa: ret = 512 << 10; break; + case 0xb: ret = 1 << 20; break; + case 0xc: ret = 2 << 20; break; + case 0xd: ret = 4 << 20; break; + case 0xe: ret = 8 << 20; break; + case 0xf: ret = 16 << 20; break; + default: ret = 0; break; + } + return ret; +} + +/** + \brief Get DTCM Size + \details Get DTCM Size + \return DTCM size (bytes). + */ +__STATIC_INLINE uint32_t csi_dtcm_get_size(void) +{ + MDTCMCR_Type sizemask; + uint32_t ret; + + sizemask.w = __get_MDTCMCR(); + switch (sizemask.b.Size) + { + case 0x3: ret = 4 << 10; break; + case 0x4: ret = 8 << 10; break; + case 0x5: ret = 16 << 10; break; + case 0x6: ret = 32 << 10; break; + case 0x7: ret = 64 << 10; break; + case 0x8: ret = 128 << 10; break; + case 0x9: ret = 256 << 10; break; + case 0xa: ret = 512 << 10; break; + case 0xb: ret = 1 << 20; break; + case 0xc: ret = 2 << 20; break; + case 0xd: ret = 4 << 20; break; + case 0xe: ret = 8 << 20; break; + case 0xf: ret = 16 << 20; break; + default: ret = 0; break; + } + return ret; +} + +/** + \brief Set ITCM Base Address + \details Set ITCM Base Address + \param [in] base_addr itcm base address. + */ +__STATIC_INLINE void csi_itcm_set_base_addr(unsigned long base_addr) +{ + __set_MITCMCR((__get_MITCMCR() & (~MITCMCR_Base_Address_Msk)) | (base_addr & MITCMCR_Base_Address_Msk)); +} + +/** + \brief Set DTCM Base Address + \details Set DTCM Base Address + \param [in] base_addr dtcm base address. + */ +__STATIC_INLINE void csi_dtcm_set_base_addr(unsigned long base_addr) +{ + __set_MDTCMCR((__get_MDTCMCR() & (~MDTCMCR_Base_Address_Msk)) | (base_addr & MDTCMCR_Base_Address_Msk)); +} + +/*@} end of CSI_Core_TCMFunctions */ +#endif /* end e907xx */ + + +/*@} end of CSI_core_DebugFunctions */ + +/* ################################## IRQ Functions ############################################ */ + +/** + \brief Save the Irq context + \details save the psr result before disable irq. + */ +__STATIC_INLINE uint32_t csi_irq_save(void) +{ + uint32_t result; + result = __get_MSTATUS(); + __disable_irq(); + return(result); +} + +/** + \brief Restore the Irq context + \details restore saved primask state. + \param [in] irq_state psr irq state. + */ +__STATIC_INLINE void csi_irq_restore(uint32_t irq_state) +{ + __set_MSTATUS(irq_state); +} + +/*@} end of IRQ Functions */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_RV32_H_DEPENDANT */ + +#endif /* __CSI_GENERIC */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/core_rv64.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/core_rv64.h new file mode 100644 index 00000000000..109a397b3db --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/core_rv64.h @@ -0,0 +1,2003 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + + +/****************************************************************************** + * @file core_rv64.h + * @brief CSI RV32 Core Peripheral Access Layer Header File + * @version V1.0 + * @date 01. Sep 2018 + ******************************************************************************/ + +#ifndef __CORE_RV64_H_GENERIC +#define __CORE_RV64_H_GENERIC + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * CSI definitions + ******************************************************************************/ +/** + \ingroup RV32 + @{ + */ + +#ifndef __RV64 +#define __RV64 (0x01U) +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __GNUC__ ) +#if defined (__VFP_FP__) && !defined(__SOFTFP__) +#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" +#endif +#endif + +#if defined(CONFIG_PLIC_BASE) +#ifndef CORET_BASE +#define CORET_BASE (CONFIG_PLIC_BASE + 0x4000000UL) /*!< CORET Base Address */ +#endif +#define PLIC ((PLIC_Type *)CONFIG_PLIC_BASE) +#else +#error "CONFIG_PLIC_BASE is not defined!" +#endif /* end CONFIG_PLIC_BASE */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_RV32_H_GENERIC */ + +#ifndef __CSI_GENERIC + +#ifndef __CORE_RV32_H_DEPENDANT +#define __CORE_RV32_H_DEPENDANT + +#ifdef __cplusplus +extern "C" { +#endif + +/* check device defines and use defaults */ +#ifndef __RV64_REV +#define __RV64_REV 0x0000U +#endif + +#ifndef __VIC_PRIO_BITS +#define __VIC_PRIO_BITS 2U +#endif + +#ifndef __Vendor_SysTickConfig +#define __Vendor_SysTickConfig 1U +#endif + +#ifndef __MPU_PRESENT +#define __MPU_PRESENT 1U +#endif + +#ifndef __ICACHE_PRESENT +#define __ICACHE_PRESENT 1U +#endif + +#ifndef __DCACHE_PRESENT +#define __DCACHE_PRESENT 1U +#endif + + +#ifndef __L2CACHE_PRESENT +#define __L2CACHE_PRESENT 1U +#endif + +#include + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CSI_glob_defs CSI Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus +#define __I volatile /*!< Defines 'read only' permissions */ +#else +#define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group C9xx/R9xx */ + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core CLINT Register + ******************************************************************************/ +/** + \defgroup CSI_core_register Defines and Type Definitions + \brief Type definitions and defines for CK80X processor based devices. +*/ + +/** + \ingroup CSI_core_register + \defgroup CSI_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +#if CONFIG_INTC_CLIC_PLIC +/** + \brief Access to the structure of a CLIC vector interrupt controller. + */ +typedef struct { + __IOM uint8_t IP; /*!< Offset: 0x000 (R/W) Interrupt set pending register */ + __IOM uint8_t IE; /*!< Offset: 0x004 (R/W) Interrupt set enable register */ + __IOM uint8_t ATTR; /*!< Offset: 0x008 (R/W) Interrupt set attribute register */ + __IOM uint8_t CTL; /*!< Offset: 0x00C (R/W) Interrupt control register */ +} CLIC_INT_Control; + +typedef struct { + __IOM uint32_t CLICCFG:8; /*!< Offset: 0x000 (R/W) CLIC configure register */ + __IM uint32_t CLICINFO; + __IOM uint32_t MINTTHRESH; + uint32_t RESERVED[1021]; + CLIC_INT_Control CLICINT[4096]; +} CLIC_Type; + +#define CLIC_INFO_CLICINTCTLBITS_Pos 21U +#define CLIC_INFO_CLICINTCTLBITS_Msk (0xFUL << CLIC_INFO_CLICINTCTLBITS_Pos) + +#define CLIC_INTIP_IP_Pos 0U /*!< CLIC INTIP: IP Position */ +#define CLIC_INTIP_IP_Msk (0x1UL << CLIC_INTIP_IP_Pos) /*!< CLIC INTIP: IP Mask */ + +#define CLIC_INTIE_IE_Pos 0U /*!< CLIC INTIE: IE Position */ +#define CLIC_INTIE_IE_Msk (0x1UL << CLIC_INTIE_IE_Pos) /*!< CLIC INTIE: IE Mask */ + +#define CLIC_INTIE_T_Pos 7U /*!< CLIC INTIE: T Position */ +#define CLIC_INTIE_T_Msk (0x1UL << CLIC_INTIE_T_Pos) /*!< CLIC INTIE: T Mask */ + +#define CLIC_INTATTR_TRIG_Pos 1U /*!< CLIC INTATTR: TRIG Position */ +#define CLIC_INTATTR_TRIG_Msk (0x3UL << CLIC_INTATTR_TRIG_Pos) /*!< CLIC INTATTR: TRIG Mask */ + +#define CLIC_INTATTR_SHV_Pos 0U /*!< CLIC INTATTR: SHV Position */ +#define CLIC_INTATTR_SHV_Msk (0x1UL << CLIC_INTATTR_SHV_Pos) /*!< CLIC INTATTR: SHV Mask */ + +#define CLIC_INTCFG_NVBIT_Pos 5U /*!< CLIC INTCFG: NVBIT Position */ +#define CLIC_INTCFG_NVBIT_Msk (0x1UL << CLIC_INTCFG_NVBIT_Pos) /*!< CLIC INTCFG: NVBIT Mask */ + +#define CLIC_INTCFG_PRIO_Pos 5U /*!< CLIC INTCFG: INTCFG Position */ +#define CLIC_INTCFG_PRIO_Msk (0x7UL << CLIC_INTCFG_PRIO_Pos) /*!< CLIC INTCFG: INTCFG Mask */ + +#define CLIC_CLICCFG_NVBIT_Pos 0U /*!< CLIC CLICCFG: NVBIT Position */ +#define CLIC_CLICCFG_NVBIT_Msk (0x1UL << CLIC_CLICCFG_NVBIT_Pos) /*!< CLIC CLICCFG: NVBIT Mask */ + +#define CLIC_CLICCFG_NLBIT_Pos 1U /*!< CLIC CLICCFG: NLBIT Position */ +#define CLIC_CLICCFG_NLBIT_Msk (0xFUL << CLIC_CLICCFG_NLBIT_Pos) /*!< CLIC CLICCFG: NLBIT Mask */ + +#define CLIC_CLICCFG_NMBIT_Pos 5U /*!< CLIC CLICCFG: NMBIT Position */ +#define CLIC_CLICCFG_NMBIT_Msk (0x3UL << CLIC_CLICCFG_NMBIT_Pos) /*!< CLIC CLICCFG: NMBIT Mask */ + +#if defined(CONFIG_CLIC_BASE) +#define CLIC ((CLIC_Type *)CONFIG_CLIC_BASE) /*!< CLIC configuration struct */ +#else +#error "CONFIG_CLIC_BASE is not defined!" +#endif /* end CONFIG_CLIC_BASE */ + +#endif /* CONFIG_INTC_CLIC_PLIC */ + + +/** + \brief Access to the structure of a PLIC vector interrupt controller. + */ + +typedef struct { + uint32_t RESERVED0; /*!< Offset: 0x000 (R/W) CLINT configure register */ + __IOM uint32_t PLIC_PRIO[1023]; + __IOM uint32_t PLIC_IP[32]; + uint32_t RESERVED1[3972 / 4 - 1]; + __IOM uint32_t PLIC_H0_MIE[32]; + __IOM uint32_t PLIC_H0_SIE[32]; + __IOM uint32_t PLIC_H1_MIE[32]; + __IOM uint32_t PLIC_H1_SIE[32]; + __IOM uint32_t PLIC_H2_MIE[32]; + __IOM uint32_t PLIC_H2_SIE[32]; + __IOM uint32_t PLIC_H3_MIE[32]; + __IOM uint32_t PLIC_H3_SIE[32]; + __IOM uint32_t PLIC_H4_MIE[32]; + __IOM uint32_t PLIC_H4_SIE[32]; + __IOM uint32_t PLIC_H5_MIE[32]; + __IOM uint32_t PLIC_H5_SIE[32]; + __IOM uint32_t PLIC_H6_MIE[32]; + __IOM uint32_t PLIC_H6_SIE[32]; + __IOM uint32_t PLIC_H7_MIE[32]; + __IOM uint32_t PLIC_H7_SIE[32]; + + uint32_t RESERVED2[(0x01FFFFC - 0x00027FC) / 4 - 1]; + __IOM uint32_t PLIC_PER; + __IOM uint32_t PLIC_H0_MTH; + __IOM uint32_t PLIC_H0_MCLAIM; + uint32_t RESERVED3[0xFFC / 4 - 1]; + __IOM uint32_t PLIC_H0_STH; + __IOM uint32_t PLIC_H0_SCLAIM; + uint32_t RESERVED4[0xFFC / 4 - 1]; + + __IOM uint32_t PLIC_H1_MTH; + __IOM uint32_t PLIC_H1_MCLAIM; + uint32_t RESERVED5[0xFFC / 4 - 1]; + __IOM uint32_t PLIC_H1_STH; + __IOM uint32_t PLIC_H1_SCLAIM; + uint32_t RESERVED6[0xFFC / 4 - 1]; + + __IOM uint32_t PLIC_H2_MTH; + __IOM uint32_t PLIC_H2_MCLAIM; + uint32_t RESERVED7[0xFFC / 4 - 1]; + __IOM uint32_t PLIC_H2_STH; + __IOM uint32_t PLIC_H2_SCLAIM; + uint32_t RESERVED8[0xFFC / 4 - 1]; + + __IOM uint32_t PLIC_H3_MTH; + __IOM uint32_t PLIC_H3_MCLAIM; + uint32_t RESERVED9[0xFFC / 4 - 1]; + __IOM uint32_t PLIC_H3_STH; + __IOM uint32_t PLIC_H3_SCLAIM; + uint32_t RESERVED10[0xFFC / 4 - 1]; + + __IOM uint32_t PLIC_H4_MTH; + __IOM uint32_t PLIC_H4_MCLAIM; + uint32_t RESERVED11[0xFFC / 4 - 1]; + __IOM uint32_t PLIC_H4_STH; + __IOM uint32_t PLIC_H4_SCLAIM; + uint32_t RESERVED12[0xFFC / 4 - 1]; + + __IOM uint32_t PLIC_H5_MTH; + __IOM uint32_t PLIC_H5_MCLAIM; + uint32_t RESERVED13[0xFFC / 4 - 1]; + __IOM uint32_t PLIC_H5_STH; + __IOM uint32_t PLIC_H5_SCLAIM; + uint32_t RESERVED14[0xFFC / 4 - 1]; + + __IOM uint32_t PLIC_H6_MTH; + __IOM uint32_t PLIC_H6_MCLAIM; + uint32_t RESERVED15[0xFFC / 4 - 1]; + __IOM uint32_t PLIC_H6_STH; + __IOM uint32_t PLIC_H6_SCLAIM; + uint32_t RESERVED16[0xFFC / 4 - 1]; + + __IOM uint32_t PLIC_H7_MTH; + __IOM uint32_t PLIC_H7_MCLAIM; + uint32_t RESERVED17[0xFFC / 4 - 1]; + __IOM uint32_t PLIC_H7_STH; + __IOM uint32_t PLIC_H7_SCLAIM; + uint32_t RESERVED18[0xFFC / 4 - 1]; +} PLIC_Type; + + +/** + \ingroup CSI_core_register + \defgroup CSI_PMP Physical Memory Protection (PMP) + \brief Type definitions for the PMP Registers + @{ + */ + +#define PMP_PMPCFG_R_Pos 0U /*!< PMP PMPCFG: R Position */ +#define PMP_PMPCFG_R_Msk (0x1UL << PMP_PMPCFG_R_Pos) /*!< PMP PMPCFG: R Mask */ + +#define PMP_PMPCFG_W_Pos 1U /*!< PMP PMPCFG: W Position */ +#define PMP_PMPCFG_W_Msk (0x1UL << PMP_PMPCFG_W_Pos) /*!< PMP PMPCFG: W Mask */ + +#define PMP_PMPCFG_X_Pos 2U /*!< PMP PMPCFG: X Position */ +#define PMP_PMPCFG_X_Msk (0x1UL << PMP_PMPCFG_X_Pos) /*!< PMP PMPCFG: X Mask */ + +#define PMP_PMPCFG_A_Pos 3U /*!< PMP PMPCFG: A Position */ +#define PMP_PMPCFG_A_Msk (0x3UL << PMP_PMPCFG_A_Pos) /*!< PMP PMPCFG: A Mask */ + +#define PMP_PMPCFG_L_Pos 7U /*!< PMP PMPCFG: L Position */ +#define PMP_PMPCFG_L_Msk (0x1UL << PMP_PMPCFG_L_Pos) /*!< PMP PMPCFG: L Mask */ + +typedef enum { + REGION_SIZE_4B = -1, + REGION_SIZE_8B = 0, + REGION_SIZE_16B = 1, + REGION_SIZE_32B = 2, + REGION_SIZE_64B = 3, + REGION_SIZE_128B = 4, + REGION_SIZE_256B = 5, + REGION_SIZE_512B = 6, + REGION_SIZE_1KB = 7, + REGION_SIZE_2KB = 8, + REGION_SIZE_4KB = 9, + REGION_SIZE_8KB = 10, + REGION_SIZE_16KB = 11, + REGION_SIZE_32KB = 12, + REGION_SIZE_64KB = 13, + REGION_SIZE_128KB = 14, + REGION_SIZE_256KB = 15, + REGION_SIZE_512KB = 16, + REGION_SIZE_1MB = 17, + REGION_SIZE_2MB = 18, + REGION_SIZE_4MB = 19, + REGION_SIZE_8MB = 20, + REGION_SIZE_16MB = 21, + REGION_SIZE_32MB = 22, + REGION_SIZE_64MB = 23, + REGION_SIZE_128MB = 24, + REGION_SIZE_256MB = 25, + REGION_SIZE_512MB = 26, + REGION_SIZE_1GB = 27, + REGION_SIZE_2GB = 28, + REGION_SIZE_4GB = 29, + REGION_SIZE_8GB = 30, + REGION_SIZE_16GB = 31 +} region_size_e; + +typedef enum { + ADDRESS_MATCHING_TOR = 1, + ADDRESS_MATCHING_NAPOT = 3 +} address_matching_e; + +typedef struct { + uint32_t r: 1; /* readable enable */ + uint32_t w: 1; /* writeable enable */ + uint32_t x: 1; /* execable enable */ + address_matching_e a: 2; /* address matching mode */ + uint32_t reserved: 2; /* reserved */ + uint32_t l: 1; /* lock enable */ +} mpu_region_attr_t; + +/*@} end of group CSI_PMP */ + +/* CACHE Register Definitions */ +#define CACHE_MHCR_WBR_Pos 8U /*!< CACHE MHCR: WBR Position */ +#define CACHE_MHCR_WBR_Msk (0x1UL << CACHE_MHCR_WBR_Pos) /*!< CACHE MHCR: WBR Mask */ + +#define CACHE_MHCR_IBPE_Pos 7U /*!< CACHE MHCR: IBPE Position */ +#define CACHE_MHCR_IBPE_Msk (0x1UL << CACHE_MHCR_IBPE_Pos) /*!< CACHE MHCR: IBPE Mask */ + +#define CACHE_MHCR_BTB_Pos 6U /*!< CACHE MHCR: BTB Position */ +#define CACHE_MHCR_BTB_Msk (0x1UL << CACHE_MHCR_BTB_Pos) /*!< CACHE MHCR: BTB Mask */ + +#define CACHE_MHCR_BPE_Pos 5U /*!< CACHE MHCR: BPE Position */ +#define CACHE_MHCR_BPE_Msk (0x1UL << CACHE_MHCR_BPE_Pos) /*!< CACHE MHCR: BPE Mask */ + +#define CACHE_MHCR_RS_Pos 4U /*!< CACHE MHCR: RS Position */ +#define CACHE_MHCR_RS_Msk (0x1UL << CACHE_MHCR_RS_Pos) /*!< CACHE MHCR: RS Mask */ + +#define CACHE_MHCR_WB_Pos 3U /*!< CACHE MHCR: WB Position */ +#define CACHE_MHCR_WB_Msk (0x1UL << CACHE_MHCR_WB_Pos) /*!< CACHE MHCR: WB Mask */ + +#define CACHE_MHCR_WA_Pos 2U /*!< CACHE MHCR: WA Position */ +#define CACHE_MHCR_WA_Msk (0x1UL << CACHE_MHCR_WA_Pos) /*!< CACHE MHCR: WA Mask */ + +#define CACHE_MHCR_DE_Pos 1U /*!< CACHE MHCR: DE Position */ +#define CACHE_MHCR_DE_Msk (0x1UL << CACHE_MHCR_DE_Pos) /*!< CACHE MHCR: DE Mask */ + +#define CACHE_MHCR_IE_Pos 0U /*!< CACHE MHCR: IE Position */ +#define CACHE_MHCR_IE_Msk (0x1UL << CACHE_MHCR_IE_Pos) /*!< CACHE MHCR: IE Mask */ + +#if CONFIG_CPU_XUANTIE_R908 || CONFIG_CPU_XUANTIE_R908FD || CONFIG_CPU_XUANTIE_R908FDV \ + || CONFIG_CPU_XUANTIE_R908_CP || CONFIG_CPU_XUANTIE_R908FD_CP || CONFIG_CPU_XUANTIE_R908FDV_CP +#define MCER_ECC_FATAL_Pos 34U +#define MCER_ECC_FATAL_Msk (0x1ULL << MCER_ECC_FATAL_Pos) + +#define MCER_ECC_VLD_Pos 35U +#define MCER_ECC_VLD_Msk (0x1ULL << MCER_ECC_VLD_Pos) + +#define MCER_RAMID_Pos 25U +#define MCER_RAMID_Msk (0x7ULL << MCER_RAMID_Pos) +#else +#define MCER_ECC_FATAL_Pos 30U +#define MCER_ECC_FATAL_Msk (0x1ULL << MCER_ECC_FATAL_Pos) +#define MCER_ECC_VLD_Pos 31U +#define MCER_ECC_VLD_Msk (0x1ULL << MCER_ECC_VLD_Pos) +#define MCER_RAMID_Pos 21U +#define MCER_RAMID_Msk (0x7ULL << MCER_RAMID_Pos) +#endif + +#define CACHE_MCER2_ECC_FATAL_Pos 62U +#define CACHE_MCER2_ECC_FATAL_Msk (0x1ULL << CACHE_MCER2_ECC_FATAL_Pos) + +#define CACHE_MCER2H_ECC_FATAL_Pos 30U +#define CACHE_MCER2H_ECC_FATAL_Msk (0x1ULL << CACHE_MCER2H_ECC_FATAL_Pos) + +#define CACHE_MCER2_ECC_VLD_Pos 63U +#define CACHE_MCER2_ECC_VLD_Msk (0x1ULL << CACHE_MCER2_ECC_VLD_Pos) + +#define CACHE_MCER2H_ECC_VLD_Pos 31U +#define CACHE_MCER2H_ECC_VLD_Msk (0x1ULL << CACHE_MCER2H_ECC_VLD_Pos) + +#define CACHE_MCER2_RAMID_Pos 53U +#define CACHE_MCER2_RAMID_Msk (0x3ULL << CACHE_MCER2_RAMID_Pos) + +#define CACHE_MCER2H_RAMID_Pos 21U +#define CACHE_MCER2H_RAMID_Msk (0x3ULL << CACHE_MCER2H_RAMID_Pos) + +#define CACHE_INV_ADDR_Pos 6U +#define CACHE_INV_ADDR_Msk (0xFFFFFFFFULL << CACHE_INV_ADDR_Pos) + +enum MCER_FAULT_RAMID { + /* L1 Cache, JTLB and TCM (RAMID of MCER)*/ + MCER_FAULT_RAMID_L1_ICACHE_TAG = 0, + MCER_FAULT_RAMID_L1_ICACHE_DATA, + MCER_FAULT_RAMID_L1_DCACHE_TAG, + MCER_FAULT_RAMID_L1_DCACHE_DATA, + MCER_FAULT_RAMID_JTLB_TAG, + MCER_FAULT_RAMID_JTLB_DATA, + MCER_FAULT_RAMID_DTCM, + MCER_FAULT_RAMID_ITCM +}; + +enum MCER2_FAULT_RAMID { + MCER2_FAULT_RAMID_L2_CACHE_TAG = 0, + MCER2_FAULT_RAMID_L2_CACHE_DATA, + MCER2_FAULT_RAMID_L2_CACHE_DIRTY +}; + +/*@} end of group CSI_CACHE */ + +// MSTATUS Register +#define MSTATUS_TVM_MASK (1L << 20) // mstatus.TVM [20] +#define MSTATUS_MPP_MASK (3L << 11) // mstatus.SPP [11:12] +#ifndef MSTATUS_MPP_M +#define MSTATUS_MPP_M (3L << 11) // Machine mode 11 +#endif +#define MSTATUS_MPP_S (1L << 11) // Supervisor mode 01 +#define MSTATUS_MPP_U (0L << 11) // User mode 00 + +// SSTATUS Register +#define SSTATUS_SPP_MASK (3L << 8) // sstatus.SPP [8:9] +#define SSTATUS_SPP_S (1L << 8) // Supervisor mode 01 +#define SSTATUS_SPP_U (0L << 8) // User mode 00 + +typedef enum { + USER_MODE = 0, + SUPERVISOR_MODE = 1, + MACHINE_MODE = 3, +} cpu_work_mode_t; + +/** + \brief Get CPU WORK MODE + \details Returns CPU WORK MODE. + \return CPU WORK MODE + */ +__STATIC_INLINE int csi_get_cpu_work_mode(void) +{ + return (int)__get_CPU_WORK_MODE(); +} + +/** + \brief Get current hartid + \return hartid + */ +__STATIC_INLINE int csi_get_cpu_id(void) +{ + unsigned long result; + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + return 0; +#endif + __ASM volatile("csrr %0, mhartid" : "=r"(result) : : "memory"); + return result; +} + +/** + \brief Get cache line size + \return cache line size + */ +__STATIC_INLINE int csi_get_cache_line_size(void) +{ + return 64; +} + + +/** + \ingroup CSI_core_register + \defgroup CSI_CINT Core Local Interrupt (CLINT) + \brief Type definitions for the Core Local Interrupt Registers. + @{ + */ + +/** + \brief The data structure of the access Clint. + */ +typedef struct { + __IOM uint32_t MSIP0; + __IOM uint32_t MSIP1; + __IOM uint32_t MSIP2; + __IOM uint32_t MSIP3; + __IOM uint32_t MSIP4; + __IOM uint32_t MSIP5; + __IOM uint32_t MSIP6; + __IOM uint32_t MSIP7; + uint32_t RESERVED0[(0x4004000 - 0x400001C) / 4 - 1]; + __IOM uint32_t MTIMECMPL0; + __IOM uint32_t MTIMECMPH0; + __IOM uint32_t MTIMECMPL1; + __IOM uint32_t MTIMECMPH1; + __IOM uint32_t MTIMECMPL2; + __IOM uint32_t MTIMECMPH2; + __IOM uint32_t MTIMECMPL3; + __IOM uint32_t MTIMECMPH3; + __IOM uint32_t MTIMECMPL4; + __IOM uint32_t MTIMECMPH4; + __IOM uint32_t MTIMECMPL5; + __IOM uint32_t MTIMECMPH5; + __IOM uint32_t MTIMECMPL6; + __IOM uint32_t MTIMECMPH6; + __IOM uint32_t MTIMECMPL7; + __IOM uint32_t MTIMECMPH7; + uint32_t RESERVED1[(0x400BFF8 - 0x400403C) / 4 - 1]; + __IOM uint32_t MTIMEL; + __IOM uint32_t MTIMEH; + __IOM uint32_t SSIP0; + __IOM uint32_t SSIP1; + __IOM uint32_t SSIP2; + __IOM uint32_t SSIP3; + __IOM uint32_t SSIP4; + __IOM uint32_t SSIP5; + __IOM uint32_t SSIP6; + __IOM uint32_t SSIP7; + uint32_t RESERVED2[(0x400D000 - 0x400C01C) / 4 - 1]; + __IOM uint32_t STIMECMPL0; + __IOM uint32_t STIMECMPH0; + __IOM uint32_t STIMECMPL1; + __IOM uint32_t STIMECMPH1; + __IOM uint32_t STIMECMPL2; + __IOM uint32_t STIMECMPH2; + __IOM uint32_t STIMECMPL3; + __IOM uint32_t STIMECMPH3; + __IOM uint32_t STIMECMPL4; + __IOM uint32_t STIMECMPH4; + __IOM uint32_t STIMECMPL5; + __IOM uint32_t STIMECMPH5; + __IOM uint32_t STIMECMPL6; + __IOM uint32_t STIMECMPH6; + __IOM uint32_t STIMECMPL7; + __IOM uint32_t STIMECMPH7; + uint32_t RESERVED3[(0x400FFF8 - 0x400D03C) / 4 - 1]; + __IOM uint32_t STIMEL; + __IOM uint32_t STIMEH; +} CLINT_Type; + +typedef struct { +#ifdef CONFIG_RISCV_SMODE + __IOM uint32_t STIMECMPL0; + __IOM uint32_t STIMECMPH0; +#else + __IOM uint32_t MTIMECMPL0; + __IOM uint32_t MTIMECMPH0; +#endif +} CLINT_CMP_Type; + +/*@} end of group CSI_SysTick */ + + +/** + \ingroup CSI_core_register + \defgroup CSI_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CSI_core_bitfield */ + +/** + \ingroup CSI_core_register + \defgroup CSI_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/*@} */ + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core VIC Functions + - Core CORET Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CSI_Core_FunctionInterface Functions and Instructions Reference +*/ + +/* ########################## VIC functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_VICFunctions VIC Functions + \brief Functions that manage interrupts and exceptions via the VIC. + @{ + */ + +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 5UL) ) +#define _IP2_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +#define PLIC_Hn_MSIE_ADDR(msie_base, hartid) ((unsigned long)(msie_base) + 0x100 * (hartid)) +#define PLIC_Hn_MSIE_VAL(msie_base, hartid) (*(__IOM uint32_t *)(PLIC_Hn_MSIE_ADDR(msie_base, hartid))) +#define PLIC_Hn_MSTH_ADDR(msth_base, hartid) ((unsigned long)(msth_base) + 0x2000 * (hartid)) +#define PLIC_Hn_MSTH_VAL(msth_base, hartid) (*(__IOM uint32_t *)(PLIC_Hn_MSTH_ADDR(msth_base, hartid))) +#define PLIC_Hn_MSCLAIM_ADDR(msclaim_base, hartid) ((unsigned long)(msclaim_base) + 0x2000 * (hartid)) +#define PLIC_Hn_MSCLAIM_VAL(msclaim_base, hartid) (*(__IOM uint32_t *)(PLIC_Hn_MSCLAIM_ADDR(msclaim_base, hartid))) + +/** + \brief Enable External Interrupt + \details Enable a device-specific interrupt in the VIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_enable_irq(int32_t IRQn) +{ + int hartid = csi_get_cpu_id(); + PLIC_Type *plic = (PLIC_Type *)CONFIG_PLIC_BASE; + +#if CONFIG_INTC_CLIC_PLIC + if (IRQn > PLIC_IRQ_OFFSET) { + IRQn -= PLIC_IRQ_OFFSET; + } else { + CLIC->CLICINT[IRQn].IE |= CLIC_INTIE_IE_Msk; + __DSB(); + return; + } +#endif +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_SIE[IRQn/32], hartid) = PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_SIE[IRQn/32], hartid) | (0x1 << (IRQn%32)); +#else + PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_MIE[IRQn/32], hartid) = PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_MIE[IRQn/32], hartid) | (0x1 << (IRQn%32)); +#endif +} + +/** + \brief Enable External Interrupt(deprecated) + \details Enable a device-specific interrupt in the VIC interrupt controller. + \param [in] plic_base PLIC base address + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_plic_enable_irq(unsigned long plic_base, int32_t IRQn) +{ + int hartid = csi_get_cpu_id(); + PLIC_Type *plic = (PLIC_Type *)plic_base; + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_SIE[IRQn/32], hartid) = PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_SIE[IRQn/32], hartid) | (0x1 << (IRQn%32)); +#else + PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_MIE[IRQn/32], hartid) = PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_MIE[IRQn/32], hartid) | (0x1 << (IRQn%32)); +#endif +} + +/** + \brief Disable External Interrupt + \details Disable a device-specific interrupt in the VIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_disable_irq(int32_t IRQn) +{ + int hartid = csi_get_cpu_id(); + PLIC_Type *plic = (PLIC_Type *)CONFIG_PLIC_BASE; + +#if CONFIG_INTC_CLIC_PLIC + if (IRQn > PLIC_IRQ_OFFSET) { + IRQn -= PLIC_IRQ_OFFSET; + } else { + CLIC->CLICINT[IRQn].IE &= ~CLIC_INTIE_IE_Msk; + __DSB(); + return; + } +#endif +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_SIE[IRQn/32], hartid) = PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_SIE[IRQn/32], hartid) & (~(0x1 << (IRQn%32))); +#else + PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_MIE[IRQn/32], hartid) = PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_MIE[IRQn/32], hartid) & (~(0x1 << (IRQn%32))); +#endif +} + +/** + \brief Disable External Interrupt(deprecated) + \details Disable a device-specific interrupt in the VIC interrupt controller. + \param [in] plic_base PLIC base address + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_plic_disable_irq(unsigned long plic_base, int32_t IRQn) +{ + int hartid = csi_get_cpu_id(); + PLIC_Type *plic = (PLIC_Type *)plic_base; + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_SIE[IRQn/32], hartid) = PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_SIE[IRQn/32], hartid) & (~(0x1 << (IRQn%32))); +#else + PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_MIE[IRQn/32], hartid) = PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_MIE[IRQn/32], hartid) & (~(0x1 << (IRQn%32))); +#endif +} + +/** + \brief Check Interrupt is Enabled or not + \details Read the enabled register in the VIC and returns the pending bit for the specified interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + \return 0 Interrupt status is not enabled. + \return 1 Interrupt status is enabled. + */ +__STATIC_INLINE uint32_t csi_vic_get_enabled_irq(int32_t IRQn) +{ + int hartid = csi_get_cpu_id(); + PLIC_Type *plic = (PLIC_Type *)CONFIG_PLIC_BASE; + +#if CONFIG_INTC_CLIC_PLIC + if (IRQn > PLIC_IRQ_OFFSET) { + IRQn -= PLIC_IRQ_OFFSET; + } else { + return (uint32_t)(CLIC->CLICINT[IRQn].IE & CLIC_INTIE_IE_Msk); + } +#endif +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + return (uint32_t)((PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_SIE[IRQn/32], hartid) >> IRQn%32) & 0x1); +#else + return (uint32_t)((PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_MIE[IRQn/32], hartid) >> IRQn%32) & 0x1); +#endif +} + +/** + \brief Check Interrupt is Enabled or not(deprecated) + \details Read the enabled register in the VIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not enabled. + \return 1 Interrupt status is enabled. + */ +__STATIC_INLINE uint32_t csi_plic_get_enabled_irq(unsigned long plic_base, int32_t IRQn) +{ + int hartid = csi_get_cpu_id(); + PLIC_Type *plic = (PLIC_Type *)plic_base; + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + return (uint32_t)((PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_SIE[IRQn/32], hartid) >> IRQn%32) & 0x1); +#else + return (uint32_t)((PLIC_Hn_MSIE_VAL(&plic->PLIC_H0_MIE[IRQn/32], hartid) >> IRQn%32) & 0x1); +#endif +} + +/** + \brief Check Interrupt is Pending or not + \details Read the pending register in the VIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t csi_vic_get_pending_irq(int32_t IRQn) +{ + PLIC_Type *plic = (PLIC_Type *)CONFIG_PLIC_BASE; +#if CONFIG_INTC_CLIC_PLIC + if (IRQn > PLIC_IRQ_OFFSET) { + IRQn -= PLIC_IRQ_OFFSET; + } else { + return (uint32_t)(CLIC->CLICINT[IRQn].IP & CLIC_INTIP_IP_Msk); + } +#endif + return (uint32_t)((plic->PLIC_IP[IRQn/32] >> IRQn%32) & 0x1); +} + +/** + \brief Set Pending Interrupt + \details Set the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_set_pending_irq(int32_t IRQn) +{ + PLIC_Type *plic = (PLIC_Type *)CONFIG_PLIC_BASE; +#if CONFIG_INTC_CLIC_PLIC + if (IRQn > PLIC_IRQ_OFFSET) { + IRQn -= PLIC_IRQ_OFFSET; + } else { + CLIC->CLICINT[IRQn].IP |= CLIC_INTIP_IP_Msk; + return; + } +#endif + plic->PLIC_IP[IRQn/32] = plic->PLIC_IP[IRQn/32] | (0x1 << (IRQn%32)); +} + +/** + \brief Clear Pending Interrupt + \details Clear the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_vic_clear_pending_irq(int32_t IRQn) +{ + PLIC_Type *plic = (PLIC_Type *)CONFIG_PLIC_BASE; +#if CONFIG_INTC_CLIC_PLIC + if (IRQn > PLIC_IRQ_OFFSET) { + IRQn -= PLIC_IRQ_OFFSET; + } else { + CLIC->CLICINT[IRQn].IP &= ~CLIC_INTIP_IP_Msk; + return; + } +#endif + plic->PLIC_H0_SCLAIM = IRQn; +} + +/** + \brief Check Interrupt is Pending or not(deprecated) + \details Read the pending register in the VIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t csi_plic_get_pending_irq(unsigned long plic_base, int32_t IRQn) +{ + PLIC_Type *plic = (PLIC_Type *)plic_base; + return (uint32_t)((plic->PLIC_IP[IRQn/32] >> IRQn%32) & 0x1); +} + +/** + \brief Set Pending Interrupt(deprecated) + \details Set the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_plic_set_pending_irq(unsigned long plic_base, int32_t IRQn) +{ + PLIC_Type *plic = (PLIC_Type *)plic_base; + plic->PLIC_IP[IRQn/32] = plic->PLIC_IP[IRQn/32] | (0x1 << (IRQn%32)); +} + +/** + \brief Clear Pending Interrupt(deprecated) + \details Clear the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void csi_plic_clear_pending_irq(unsigned long plic_base, int32_t IRQn) +{ + PLIC_Type *plic = (PLIC_Type *)plic_base; + plic->PLIC_H0_SCLAIM = IRQn; +} + +/** + \brief Set Interrupt Priority + \details Set the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void csi_vic_set_prio(int32_t IRQn, uint32_t priority) +{ + PLIC_Type *plic = (PLIC_Type *)CONFIG_PLIC_BASE; +#if CONFIG_INTC_CLIC_PLIC + if (IRQn > PLIC_IRQ_OFFSET) { + IRQn -= PLIC_IRQ_OFFSET; + } else { + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + CLIC->CLICINT[IRQn].CTL = (CLIC->CLICINT[IRQn].CTL & (~CLIC_INTCFG_PRIO_Msk)) | (priority << (8 - nlbits)); + __DSB(); + return; + } +#endif + plic->PLIC_PRIO[IRQn - 1] = priority; +} + +/** + \brief Get Interrupt Priority + \details Read the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t csi_vic_get_prio(int32_t IRQn) +{ + PLIC_Type *plic = (PLIC_Type *)CONFIG_PLIC_BASE; +#if CONFIG_INTC_CLIC_PLIC + if (IRQn > PLIC_IRQ_OFFSET) { + IRQn -= PLIC_IRQ_OFFSET; + } else { + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + return CLIC->CLICINT[IRQn].CTL >> (8 - nlbits); + } +#endif + uint32_t prio = plic->PLIC_PRIO[IRQn - 1]; + return prio; +} + +/** + \brief Set Interrupt Priority(deprecated) + \details Set the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void csi_plic_set_prio(unsigned long plic_base, int32_t IRQn, uint32_t priority) +{ + PLIC_Type *plic = (PLIC_Type *)plic_base; + plic->PLIC_PRIO[IRQn - 1] = priority; +} + +/** + \brief Get Interrupt Priority(deprecated) + \details Read the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t csi_plic_get_prio(unsigned long plic_base, int32_t IRQn) +{ + PLIC_Type *plic = (PLIC_Type *)plic_base; + uint32_t prio = plic->PLIC_PRIO[IRQn - 1]; + return prio; +} + +/*@} end of CSI_Core_VICFunctions */ + +/* ########################## PMP functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_PMPFunctions PMP Functions + \brief Functions that manage interrupts and exceptions via the VIC. + @{ + */ + +/** + \brief configure memory protected region. + \details + \param [in] idx memory protected region (0, 1, 2, ..., 15). + \param [in] base_addr base address must be aligned with page size. + \param [in] size \ref region_size_e. memory protected region size. + \param [in] attr \ref region_size_t. memory protected region attribute. + \param [in] enable enable or disable memory protected region. + */ +__STATIC_INLINE void csi_mpu_config_region(uint32_t idx, uint32_t base_addr, region_size_e size, + mpu_region_attr_t attr, uint32_t enable) +{ + uint8_t pmpxcfg = 0; + uint32_t addr = 0; + + if (idx > 15) { + return; + } + + if (!enable) { + attr.a = (address_matching_e)0; + } + + if (attr.a == ADDRESS_MATCHING_TOR) { + addr = base_addr >> 2; + } else { + if (size == REGION_SIZE_4B) { + addr = base_addr >> 2; + attr.a = (address_matching_e)2; + } else { + addr = ((base_addr >> 2) & (0xFFFFFFFFU - ((1 << (size + 1)) - 1))) | ((1 << size) - 1); + } + } + + __set_PMPADDRx(idx, addr); + + pmpxcfg |= (attr.r << PMP_PMPCFG_R_Pos) | (attr.w << PMP_PMPCFG_W_Pos) | + (attr.x << PMP_PMPCFG_X_Pos) | (attr.a << PMP_PMPCFG_A_Pos) | + (attr.l << PMP_PMPCFG_L_Pos); + + __set_PMPxCFG(idx, pmpxcfg); +} + +/** + \brief disable mpu region by idx. + \details + \param [in] idx memory protected region (0, 1, 2, ..., 15). + */ +__STATIC_INLINE void csi_mpu_disable_region(uint32_t idx) +{ + __set_PMPxCFG(idx, __get_PMPxCFG(idx) & (~PMP_PMPCFG_A_Msk)); +} + +/*@} end of CSI_Core_PMPFunctions */ + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#define CLINT_TIMECMPn_ADDR(time_cmp_base, hartid) ((unsigned long)(time_cmp_base) + 8 * (hartid)) +#define CLINT_TIMECMPn_VAL(time_cmp_base, hartid) (*(__IOM uint32_t *)(CLINT_TIMECMPn_ADDR(time_cmp_base, hartid))) + +__STATIC_INLINE uint32_t _csi_clint_config2(unsigned long coret_base, uint16_t hartid, uint32_t ticks, int32_t IRQn) +{ + CLINT_Type *clint = (CLINT_Type *)coret_base; +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + uint64_t value = (((uint64_t)(CLINT_TIMECMPn_VAL(&clint->STIMECMPH0, hartid))) << 32) + \ + (uint64_t)(CLINT_TIMECMPn_VAL(&clint->STIMECMPL0, hartid)); + + if ((value != 0) && (value != 0xffffffffffffffff)) { + value = value + (uint64_t)ticks; + } else { + value = __get_MTIME() + ticks; + } + CLINT_TIMECMPn_VAL(&clint->STIMECMPH0, hartid) = (uint32_t)(value >> 32); + CLINT_TIMECMPn_VAL(&clint->STIMECMPL0, hartid) = (uint32_t)value; +#else + uint64_t value = (((uint64_t)(CLINT_TIMECMPn_VAL(&clint->MTIMECMPH0, hartid))) << 32) + \ + (uint64_t)(CLINT_TIMECMPn_VAL(&clint->MTIMECMPL0, hartid)); + + if ((value != 0) && (value != 0xffffffffffffffff)) { + value = value + (uint64_t)ticks; + } else { + value = __get_MTIME() + ticks; + } + CLINT_TIMECMPn_VAL(&clint->MTIMECMPH0, hartid) = (uint32_t)(value >> 32); + CLINT_TIMECMPn_VAL(&clint->MTIMECMPL0, hartid) = (uint32_t)value; +#endif + + return (0UL); +} + +__STATIC_INLINE uint32_t csi_clint_config(unsigned long coret_base, uint32_t ticks, int32_t IRQn) +{ + return _csi_clint_config2(coret_base, 0, ticks, IRQn); +} + +__STATIC_INLINE void csi_coret_reset_value2() +{ + uint32_t value = 0x0; + int hartid = csi_get_cpu_id(); + CLINT_Type *clint = (CLINT_Type *)CORET_BASE; + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + CLINT_TIMECMPn_VAL(&clint->STIMECMPH0, hartid) = (uint32_t)value; + CLINT_TIMECMPn_VAL(&clint->STIMECMPL0, hartid) = (uint32_t)value; +#else + CLINT_TIMECMPn_VAL(&clint->MTIMECMPH0, hartid) = (uint32_t)value; + CLINT_TIMECMPn_VAL(&clint->MTIMECMPL0, hartid) = (uint32_t)value; +#endif +} + +__STATIC_INLINE void csi_coret_reset_value(unsigned long coret_base) +{ + uint32_t value = 0x0; + int hartid = csi_get_cpu_id(); + CLINT_Type *clint = (CLINT_Type *)coret_base; + +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + CLINT_TIMECMPn_VAL(&clint->STIMECMPH0, hartid) = (uint32_t)value; + CLINT_TIMECMPn_VAL(&clint->STIMECMPL0, hartid) = (uint32_t)value; +#else + CLINT_TIMECMPn_VAL(&clint->MTIMECMPH0, hartid) = (uint32_t)value; + CLINT_TIMECMPn_VAL(&clint->MTIMECMPL0, hartid) = (uint32_t)value; +#endif +} + +__STATIC_INLINE uint64_t _csi_clint_get_load2(unsigned long coret_base, uint16_t hartid) +{ + CLINT_Type *clint = (CLINT_Type *)coret_base; +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + uint64_t value = (((uint64_t)CLINT_TIMECMPn_VAL(&clint->STIMECMPH0, hartid)) << 32) + \ + (uint64_t)CLINT_TIMECMPn_VAL(&clint->STIMECMPL0, hartid); +#else + uint64_t value = (((uint64_t)CLINT_TIMECMPn_VAL(&clint->MTIMECMPH0, hartid)) << 32) + \ + (uint64_t)CLINT_TIMECMPn_VAL(&clint->MTIMECMPL0, hartid); +#endif + + return value; +} + +/** + \brief get CORE timer reload high value(deprecated) + \return CORE timer counter value. + */ +__STATIC_INLINE uint64_t csi_clint_get_load(unsigned long coret_base) +{ + return _csi_clint_get_load2(coret_base, 0); +} + +__STATIC_INLINE uint32_t _csi_clint_get_loadh2(unsigned long coret_base, uint16_t hartid) +{ + CLINT_Type *clint = (CLINT_Type *)coret_base; +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + uint64_t value = (((uint64_t)CLINT_TIMECMPn_VAL(&clint->STIMECMPH0, hartid)) << 32) + \ + (uint64_t)CLINT_TIMECMPn_VAL(&clint->STIMECMPL0, hartid); +#else + uint64_t value = (((uint64_t)CLINT_TIMECMPn_VAL(&clint->MTIMECMPH0, hartid)) << 32) + \ + (uint64_t)CLINT_TIMECMPn_VAL(&clint->MTIMECMPL0, hartid); +#endif + + return (value >> 32) & 0xFFFFFFFF; +} + +/** + \brief get CORE timer reload high value(deprecated) + \return CORE timer counter value. + */ +__STATIC_INLINE uint32_t csi_clint_get_loadh(unsigned long coret_base) +{ + return _csi_clint_get_loadh2(coret_base, 0); +} + +/** + \brief get CORE timer counter value(deprecated) + \return CORE timer counter value. + */ +__STATIC_INLINE unsigned long csi_clint_get_value(void) +{ + unsigned long result; + __ASM volatile("csrr %0, time" : "=r"(result)); + return result; +} + +/** + \brief get CORE timer counter high value(deprecated) + \return CORE timer counter value. + */ +__STATIC_INLINE uint32_t csi_clint_get_valueh(void) +{ + uint64_t result; + __ASM volatile("csrr %0, time" : "=r"(result)); + return (result >> 32) & 0xFFFFFFFF; +} + +/** + \brief CORE timer Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \param [in] IRQn core timer Interrupt number. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t csi_coret_config(uint32_t ticks, int32_t IRQn) +{ + return _csi_clint_config2(CORET_BASE, csi_get_cpu_id(), ticks, IRQn); +} + +/** + \brief get CORE timer reload value + \return CORE timer counter value. + */ +__STATIC_INLINE uint64_t csi_coret_get_load2(void) +{ + return _csi_clint_get_load2(CORET_BASE, csi_get_cpu_id()); +} + +/** + \brief get CORE timer counter value + \return CORE timer counter value. + */ +__STATIC_INLINE uint64_t csi_coret_get_value2() +{ +#if __riscv_xlen == 64 + return csi_clint_get_value(); +#else + uint64_t result; + unsigned long high, low; + + __ASM volatile("csrr %0, timeh" : "=r"(high)); + __ASM volatile("csrr %0, time" : "=r"(low)); + result = ((uint64_t)high << 32) | low; + + return result; +#endif +} + +/** + \brief Enable CoreTimer(within clint) Interrupts + */ +__ALWAYS_STATIC_INLINE void csi_coret_irq_enable(void) +{ +#if CONFIG_INTC_CLIC_PLIC + extern void soc_irq_enable(uint32_t irq_num); + return soc_irq_enable(7); +#else + return __enable_coret_irq(); +#endif +} + +/** + \brief Disable CoreTimer(within clint) Interrupts + */ +__ALWAYS_STATIC_INLINE void csi_coret_irq_disable(void) +{ +#if CONFIG_INTC_CLIC_PLIC + extern void soc_irq_disable(uint32_t irq_num); + return soc_irq_disable(7); +#else + return __disable_coret_irq(); +#endif +} + + +/*@} end of CSI_core_DebugFunctions */ + +/* ########################## Cache functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_CacheFunctions Cache Functions + \brief Functions that configure Instruction and Data cache. + @{ + */ + +/** + \brief whether I-Cache enable + */ +__STATIC_INLINE int csi_icache_is_enable() +{ + uint32_t cache = __get_MHCR(); + return (cache & CACHE_MHCR_IE_Msk) >> CACHE_MHCR_IE_Pos; +} + +/** + \brief Enable I-Cache + \details Turns on I-Cache + */ +__STATIC_INLINE void csi_icache_enable(void) +{ +#if (__ICACHE_PRESENT == 1U) + if (!csi_icache_is_enable()) { + uint32_t cache; + __DSB(); + __ISB(); + __ICACHE_IALL(); + cache = __get_MHCR(); + cache |= CACHE_MHCR_IE_Msk; + __set_MHCR(cache); + __DSB(); + __ISB(); + } +#endif +} + + +/** + \brief Disable I-Cache + \details Turns off I-Cache + */ +__STATIC_INLINE void csi_icache_disable(void) +{ +#if (__ICACHE_PRESENT == 1U) + if (csi_icache_is_enable()) { + uint32_t cache; + __DSB(); + __ISB(); + cache = __get_MHCR(); + cache &= ~CACHE_MHCR_IE_Msk; /* disable icache */ + __set_MHCR(cache); + __ICACHE_IALL(); /* invalidate all icache */ + __DSB(); + __ISB(); + } +#endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_INLINE void csi_icache_invalid(void) +{ +#if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __ICACHE_IALL(); /* invalidate all icache */ + __DSB(); + __ISB(); +#endif +} + +/** + \brief whether D-Cache enable + */ +__STATIC_INLINE int csi_dcache_is_enable() +{ + uint32_t cache = __get_MHCR(); + return (cache & CACHE_MHCR_DE_Msk) >> CACHE_MHCR_DE_Pos; +} + +/** + \brief Enable D-Cache + \details Turns on D-Cache + */ +__STATIC_INLINE void csi_dcache_enable(void) +{ +#if (__DCACHE_PRESENT == 1U) + if (!csi_dcache_is_enable()) { + uint32_t cache; + __DSB(); + __ISB(); + __DCACHE_IALL(); /* invalidate all dcache */ + cache = __get_MHCR(); + cache |= CACHE_MHCR_DE_Msk; /* enable dcache */ + __set_MHCR(cache); + + __DSB(); + __ISB(); + } +#endif +} + + +/** + \brief Disable D-Cache + \details Turns off D-Cache + */ +__STATIC_INLINE void csi_dcache_disable(void) +{ +#if (__DCACHE_PRESENT == 1U) + if (csi_dcache_is_enable()) { + uint32_t cache; + __DSB(); + __ISB(); + cache = __get_MHCR(); + cache &= ~(uint32_t)CACHE_MHCR_DE_Msk; /* disable all Cache */ + __set_MHCR(cache); + __DCACHE_IALL(); /* invalidate all Cache */ + __DSB(); + __ISB(); + } +#endif +} + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_INLINE void csi_dcache_invalid(void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __DCACHE_IALL(); /* invalidate all Cache */ + __DSB(); + __ISB(); +#endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_INLINE void csi_dcache_clean(void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __DCACHE_CALL(); /* clean all Cache */ + __DSB(); + __ISB(); +#endif +} + + +/** + \brief Clean & Invalidate D-Cache + \details Cleans and Invalidates D-Cache + */ +__STATIC_INLINE void csi_dcache_clean_invalid(void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __ISB(); + __DCACHE_CIALL(); /* clean and inv all Cache */ + __DSB(); + __ISB(); +#endif +} + +/** + \brief D-Cache Invalidate by address + \details Invalidates D-Cache for the given address + \param[in] addr address (aligned to 64-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void csi_dcache_invalid_range(unsigned long *addr, size_t dsize) +{ +#if (__DCACHE_PRESENT == 1U) + int linesize = csi_get_cache_line_size(); + long op_size = dsize + (unsigned long)addr % linesize; + unsigned long op_addr = (unsigned long)addr; + + __DSB(); +#if CBO_INSN_SUPPORT + while (op_size > 0) { + __CBO_INVAL(op_addr); + op_addr += linesize; + op_size -= linesize; + } +#else + cpu_work_mode_t cpu_work_mode; + cpu_work_mode = (cpu_work_mode_t)__get_CPU_WORK_MODE(); + + if (cpu_work_mode == MACHINE_MODE) { + while (op_size > 0) { + __DCACHE_IPA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + } else if (cpu_work_mode == SUPERVISOR_MODE) { + while (op_size > 0) { + __DCACHE_IVA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + } +#endif + + __SYNC_IS(); + __DSB(); +#endif +} + + +/** + \brief D-Cache Clean by address + \details Cleans D-Cache for the given address + \param[in] addr address (aligned to 64-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void csi_dcache_clean_range(unsigned long *addr, size_t dsize) +{ + +#if (__DCACHE_PRESENT == 1) + int linesize = csi_get_cache_line_size(); + long op_size = dsize + (unsigned long)addr % linesize; + unsigned long op_addr = (unsigned long) addr & CACHE_INV_ADDR_Msk; + + __DSB(); +#if CBO_INSN_SUPPORT + while (op_size > 0) { + __CBO_CLEAN(op_addr); + op_addr += linesize; + op_size -= linesize; + } +#else + cpu_work_mode_t cpu_work_mode; + cpu_work_mode = (cpu_work_mode_t)__get_CPU_WORK_MODE(); + + if (cpu_work_mode == MACHINE_MODE) { + while (op_size > 0) { + __DCACHE_CPA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + } else if (cpu_work_mode == SUPERVISOR_MODE) { + while (op_size > 0) { + __DCACHE_CVA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + } +#endif + __SYNC_IS(); + __DSB(); +#endif + +} + + +/** + \brief D-Cache Clean and Invalidate by address + \details Cleans and invalidates D_Cache for the given address + \param[in] addr address (aligned to 64-byte boundary) + \param[in] dsize size of memory block (aligned to 64-byte boundary) +*/ +__STATIC_INLINE void csi_dcache_clean_invalid_range(unsigned long *addr, size_t dsize) +{ +#if (__DCACHE_PRESENT == 1U) + int linesize = csi_get_cache_line_size(); + long op_size = dsize + (unsigned long)addr % linesize; + unsigned long op_addr = (unsigned long) addr; + + __DSB(); +#if CBO_INSN_SUPPORT + while (op_size > 0) { + __CBO_FLUSH(op_addr); + op_addr += linesize; + op_size -= linesize; + } +#else + cpu_work_mode_t cpu_work_mode; + cpu_work_mode = (cpu_work_mode_t)__get_CPU_WORK_MODE(); + + if (cpu_work_mode == MACHINE_MODE) { + while (op_size > 0) { + __DCACHE_CIPA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + } else if (cpu_work_mode == SUPERVISOR_MODE) { + while (op_size > 0) { + __DCACHE_CIVA(op_addr); + op_addr += linesize; + op_size -= linesize; + } + } +#endif + + __SYNC_IS(); + __DSB(); +#endif +} + +/*@} end of CSI_Core_CacheFunctions */ + +/* ########################## FPP functions #################################### */ +/** + \ingroup CSI_Core_FPPFunctionInterface + \defgroup CSI_Core_FPPFunctions FPP Functions + \brief Functions that configure FPP. + @{ + */ + +/** + \ingroup CSI_fpp_register + \defgroup CSI_FPP + \brief Type definitions for the FPP Registers + @{ + */ + +/** + \brief Consortium definition for Machine Mode FPP Configuration register(MFPPCR, 0xBC0). + */ +typedef union { + struct { + uint64_t EN: 1; /*!< bit: 0 FPP enable */ + uint64_t _reversed1: 11; /*!< bit: 1 11 Reserved */ + uint64_t Base_Address: 52; /*!< bit: 12 63 Base Address */ + } b; /*!< Structure Access by bit */ + uint64_t w; /*!< Type Access by whole register */ +} MFPPCR_Type; + +#define MFPPCR_Base_Address_Pos 12U /*!< MFPPCR: Base_Address Position */ +#define MFPPCR_Base_Address_Msk (0xFFFFFFFFFFFFFULL << MFPPCR_Base_Address_Pos) /*!< MFPPCR: Base_Address Mask */ + +#define MFPPCR_Base_EN_Pos 0U /*!< MFPPCR: Enable Bit Position */ +#define MFPPCR_Base_EN_Msk (0x1U << MFPPCR_Base_EN_Pos) /*!< MFPPCR: Enable Bit Mask */ + +/*@} end of group CSI_FPP_bitfield */ + +/** + \brief Enable FPP + \details Turns on FPP + */ +__STATIC_INLINE void csi_fpp_enable(void) +{ + __set_MFPPCR(__get_MFPPCR() | MFPPCR_Base_EN_Msk); +} + +/** + \brief Disable FPP + \details Turns off FPP + */ +__STATIC_INLINE void csi_fpp_disable(void) +{ + __set_MFPPCR(__get_MFPPCR() & (~MFPPCR_Base_EN_Msk)); +} + +/** + \brief Set FPP Base Address + \details Set FPP Base Address + \param [in] base_addr FPP Base Address. + */ +__STATIC_INLINE void csi_fpp_set_base_addr(unsigned long base_addr) +{ + __set_MFPPCR((__get_MFPPCR() & (~MFPPCR_Base_Address_Msk)) + | ((base_addr << MFPPCR_Base_Address_Pos) & MFPPCR_Base_Address_Msk)); +} + +/*@} end of CSI_Core_FPPFunctions */ + + +/* ########################## MMU functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_MMUFunctions MMU Functions + \brief Functions that configure MMU. + @{ + */ + +typedef enum { + PAGE_SIZE_4KB = 0x1000, + PAGE_SIZE_2MB = 0x200000, + PAGE_SIZE_1GB = 0x40000000, +} page_size_e; + +#define MMU_MODE_32 (0x1) +#define MMU_MODE_39 (0x8) +#define MMU_MODE_48 (0x9) +#define MMU_MODE_57 (0xa) +#define MMU_MODE_64 (0xb) + +/** + \brief set mmu mode(If there are multiple mmu modes) + \param[in] mode mode of the mmu + \details + */ +__STATIC_INLINE void csi_mmu_set_mode(int mode) +{ + extern int g_mmu_mode; + g_mmu_mode = mode; +} + +/** + \brief enable mmu + \details + */ +__STATIC_INLINE void csi_mmu_enable() +{ + extern int g_mmu_mode; +#if __riscv_xlen == 64 + __set_SATP(__get_SATP() | ((unsigned long)g_mmu_mode << 60)); +#else + __set_SATP(__get_SATP() | ((unsigned long)g_mmu_mode << 31)); +#endif +} + +/** + \brief disable mmu + \details + */ +__STATIC_INLINE void csi_mmu_disable(void) +{ +#if __riscv_xlen == 64 + __set_SATP(__get_SATP() & (~((unsigned long)0xf << 60))); +#else + __set_SATP(__get_SATP() & (~((unsigned long)0x1 << 31))); +#endif +} + +/** + \brief flush all mmu tlb. + \details + */ +__STATIC_INLINE void csi_mmu_invalid_tlb_all(void) +{ + __ASM volatile("sfence.vma" : : : "memory"); +} + +/*@} end of CSI_Core_MMUFunctions */ + +/* ########################## TCM functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_TCMFunctions TCM Functions + \brief Functions that configure TCM. + @{ + */ + +#if CONFIG_CPU_XUANTIE_C907 || CONFIG_CPU_XUANTIE_C907FD || CONFIG_CPU_XUANTIE_C907FDV || CONFIG_CPU_XUANTIE_C907FDVM \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_C910V2 || CONFIG_CPU_XUANTIE_C920V2 \ + || CONFIG_CPU_XUANTIE_C910V3 || CONFIG_CPU_XUANTIE_C910V3_CP || CONFIG_CPU_XUANTIE_C920V3 || CONFIG_CPU_XUANTIE_C920V3_CP \ + || CONFIG_CPU_XUANTIE_R908 || CONFIG_CPU_XUANTIE_R908FD || CONFIG_CPU_XUANTIE_R908FDV \ + || CONFIG_CPU_XUANTIE_R908_CP || CONFIG_CPU_XUANTIE_R908FD_CP || CONFIG_CPU_XUANTIE_R908FDV_CP \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 +/** + \ingroup CSI_tcm_register + \defgroup CSI_TCM + \brief Type definitions for the tcm Registers + @{ + */ + +/** + \brief Consortium definition for accessing protection area selection register(MITCMCR, 0x7f9). + */ +typedef union { + struct { + unsigned long EN: 1; /*!< bit: 0 Instruction Tightly-Coupled Memory enable */ + unsigned long ECC_EN: 1; /*!< bit: 1 ecc_en */ + unsigned long Interleave: 1; /*!< bit: 2 Interleave */ + unsigned long _reserved1: 1; /*!< bit: 3 Reserved */ + unsigned long Size: 4; /*!< bit: 4..7 Size of ITCM */ + unsigned long _reserved2: 4; /*!< bit: 8..11 Reserved */ + unsigned long Base_Address: 52; /*!< bit: 12..63 Base address of DTCM */ + } b; /*!< Structure Access by bit */ + unsigned long w; /*!< Type Access by whole register */ +} MITCMCR_Type; + +#define MITCMCR_Base_Address_Pos 12U /*!< MITCMCR: Base_Address Position */ +#define MITCMCR_Base_Address_Msk (0xfffffffffffffULL << MITCMCR_Base_Address_Pos) /*!< MITCMCR: Base_Address Mask */ + +#define MITCMCR_Size_Pos 4U /*!< MITCMCR: Size Position */ +#define MITCMCR_Size_Msk (0xfULL << MITCMCR_Size_Pos) /*!< MITCMCR: Size Mask */ + +#define MITCMCR_INTERLEAVE_Pos 2U /*!< MITCMCR: Interleave Position */ +#define MITCMCR_INTERLEAVE_Msk (0x1ULL << MITCMCR_INTERLEAVE_Pos) /*!< MITCMCR: Interleave Mask */ + +#define MITCMCR_ECC_EN_Pos 1U /*!< MITCMCR: ECC_EN Position */ +#define MITCMCR_ECC_EN_Msk (0x1ULL << MITCMCR_ECC_EN_Pos) /*!< MITCMCR: ECC_EN Mask */ + +#define MITCMCR_EN_Pos 0U /*!< MITCMCR: EN Position */ +#define MITCMCR_EN_Msk (0x1ULL << MITCMCR_EN_Pos) /*!< MITCMCR: EN Mask */ + +/** + \brief Consortium definition for accessing protection area selection register(MDTCMCR, 0x7f8). + */ +typedef union { + struct { + unsigned long EN: 1; /*!< bit: 0 Data Tightly-Coupled Memory enable */ + unsigned long ECC_EN: 1; /*!< bit: 1 ecc_en */ + unsigned long Interleave: 1; /*!< bit: 2 Interleave */ + unsigned long _reserved1: 1; /*!< bit: 3 Reserved */ + unsigned long Size: 4; /*!< bit: 4..7 Size of ITCM */ + unsigned long _reserved2: 4; /*!< bit: 8..11 Reserved */ + unsigned long Base_Address: 52; /*!< bit: 12..63 Base address of DTCM */ + } b; /*!< Structure Access by bit */ + unsigned long w; /*!< Type Access by whole register */ +} MDTCMCR_Type; + +#define MDTCMCR_Base_Address_Pos 12U /*!< MDTCMCR: Base_Address Position */ +#define MDTCMCR_Base_Address_Msk (0xfffffffffffffULL << MDTCMCR_Base_Address_Pos) /*!< MDTCMCR: Base_Address Mask */ + +#define MDTCMCR_Size_Pos 4U /*!< MDTCMCR: Size Position */ +#define MDTCMCR_Size_Msk (0xfULL << MDTCMCR_Size_Pos) /*!< MDTCMCR: Size Mask */ + +#define MDTCMCR_INTERLEAVE_Pos 2U /*!< MDTCMCR: Interleave Position */ +#define MDTCMCR_INTERLEAVE_Msk (0x1ULL << MDTCMCR_INTERLEAVE_Pos) /*!< MDTCMCR: Interleave Mask */ + +#define MDTCMCR_ECC_EN_Pos 1U /*!< MDTCMCR: ECC_EN Position */ +#define MDTCMCR_ECC_EN_Msk (0x1ULL << MDTCMCR_ECC_EN_Pos) /*!< MDTCMCR: ECC_EN Mask */ + +#define MDTCMCR_EN_Pos 0U /*!< MDTCMCR: EN Position */ +#define MDTCMCR_EN_Msk (0x1ULL << MDTCMCR_EN_Pos) /*!< MDTCMCR: EN Mask */ + +/*@} end of group CSI_TCM_bitfield */ + +/** + \brief Enable ITCM + \details Turns on ITCM + */ +__STATIC_INLINE void csi_itcm_enable (void) +{ + __set_MITCMCR(__get_MITCMCR() | MITCMCR_EN_Msk); +} + +/** + \brief Enable DTCM + \details Turns on DTCM + */ +__STATIC_INLINE void csi_dtcm_enable (void) +{ + __set_MDTCMCR(__get_MDTCMCR() | MDTCMCR_EN_Msk); +} + +/** + \brief Enable ITCM + \details Turns on ITCM + */ +__STATIC_INLINE void csi_itcm_disable (void) +{ + __set_MITCMCR(__get_MITCMCR() & (~MITCMCR_EN_Msk)); +} + +/** + \brief Enable DTCM + \details Turns on DTCM + */ +__STATIC_INLINE void csi_dtcm_disable (void) +{ + __set_MDTCMCR(__get_MDTCMCR() & (~MDTCMCR_EN_Msk)); +} + +/** + \brief Get ITCM Size + \details Get ITCM Size + \return ITCM size (bytes). + */ +__STATIC_INLINE uint32_t csi_itcm_get_size(void) +{ + MITCMCR_Type sizemask; + uint32_t ret; + + sizemask.w = __get_MITCMCR(); + switch (sizemask.b.Size) + { + case 0x3: ret = 8 << 10; break; + case 0x4: ret = 16 << 10; break; + case 0x5: ret = 32 << 10; break; + case 0x6: ret = 64 << 10; break; + case 0x7: ret = 128 << 10; break; + case 0x8: ret = 256 << 10; break; + case 0x9: ret = 512 << 10; break; + case 0xa: ret = 1024 << 10; break; + default: ret = 0; break; + } + return ret; +} + +/** + \brief Get DTCM Size + \details Get DTCM Size + \return DTCM size (bytes). + */ +__STATIC_INLINE uint32_t csi_dtcm_get_size(void) +{ + MDTCMCR_Type sizemask; + uint32_t ret; + + sizemask.w = __get_MDTCMCR(); + switch (sizemask.b.Size) + { + case 0x3: ret = 8 << 10; break; + case 0x4: ret = 16 << 10; break; + case 0x5: ret = 32 << 10; break; + case 0x6: ret = 64 << 10; break; + case 0x8: ret = 128 << 10; break; + case 0x9: ret = 256 << 10; break; + case 0xa: ret = 512 << 10; break; + case 0xb: ret = 1024 << 10; break; + default:ret = 0; break; + } + return ret; +} + +/** + \brief Set ITCM Base Address + \details Set ITCM Base Address + \param [in] base_addr itcm base address. + */ +__STATIC_INLINE void csi_itcm_set_base_addr(unsigned long base_addr) +{ + __set_MITCMCR((__get_MITCMCR() & (~MITCMCR_Base_Address_Msk)) | (base_addr << MITCMCR_Base_Address_Pos)); +} + +/** + \brief Set DTCM Base Address + \details Set DTCM Base Address + \param [in] base_addr dtcm base address. + */ +__STATIC_INLINE void csi_dtcm_set_base_addr(unsigned long base_addr) +{ + __set_MDTCMCR((__get_MDTCMCR() & (~MDTCMCR_Base_Address_Msk)) | (base_addr << MDTCMCR_Base_Address_Pos)); +} + +/*@} end of CSI_Core_TCMFunctions */ + +/* ########################## ECC functions #################################### */ + +/** + * \brief Enable ITCM-ECC + * \details Turns on ITCM-ECC + * */ +__STATIC_INLINE void csi_itcm_ecc_enable (void) +{ + __set_MITCMCR(__get_MITCMCR() | MITCMCR_ECC_EN_Msk); +} + +/** + * \brief Disable ITCM-ECC + * \details Turns off ITCM-ECC + * */ +__STATIC_INLINE void csi_itcm_ecc_disable (void) +{ + __set_MITCMCR(__get_MITCMCR() & (~MITCMCR_ECC_EN_Msk)); +} + +/** + * \brief Enable DTCM-ECC + * \details Turns on DTCM-ECC + * */ +__STATIC_INLINE void csi_dtcm_ecc_enable (void) +{ + __set_MDTCMCR(__get_MDTCMCR() | MDTCMCR_ECC_EN_Msk); +} + +/** + * \brief Disable DTCM-ECC + * \details Turns off DTCM-ECC + * */ +__STATIC_INLINE void csi_dtcm_ecc_disable (void) +{ + __set_MDTCMCR(__get_MDTCMCR() & (~MDTCMCR_ECC_EN_Msk)); +} + +/*@} end of CSI_Core_ECCFunctions */ +#endif /* end ecc */ + +/* ################################## IRQ Functions ############################################ */ + +/** + \brief Save the Irq context + \details save the psr result before disable irq. + */ +__STATIC_INLINE unsigned long csi_irq_save(void) +{ + unsigned long result; +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + result = __get_SSTATUS(); +#else + result = __get_MSTATUS(); +#endif + __disable_irq(); + return(result); +} + +/** + \brief Restore the Irq context + \details restore saved primask state. + \param [in] irq_state psr irq state. + */ +__STATIC_INLINE void csi_irq_restore(unsigned long irq_state) +{ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + __set_SSTATUS(irq_state); +#else + __set_MSTATUS(irq_state); +#endif +} + +/*@} end of IRQ Functions */ + +/** + \brief Get the byte-width of vector register + \return the byte-width of vector register + */ +__STATIC_INLINE int csi_vlenb_get_value(void) +{ + int result; + __ASM volatile("csrr %0, vlenb" : "=r"(result) : : "memory"); + return result; +} + +#if __riscv_matrix || __riscv_xtheadmatrix +/** + \brief Get the bytes of matrix per register + \return the bytes of matrix per register + */ +__STATIC_INLINE int csi_xmlenb_get_value(void) +{ + int result; + __ASM volatile("csrr %0, xmlenb" : "=r"(result) : : "memory"); + return result; +} +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_RV32_H_DEPENDANT */ + +#endif /* __CSI_GENERIC */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_arm64_gcc.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_arm64_gcc.h new file mode 100644 index 00000000000..b62de27b929 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_arm64_gcc.h @@ -0,0 +1,3286 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + + +/****************************************************************************** + * @file csi_arm64_gcc.h + * @brief CSI Header File for GCC. + * @version V1.0 + * @date 01. Sep 2018 + ******************************************************************************/ + +#ifndef _CSI_ARM64_GCC_H_ +#define _CSI_ARM64_GCC_H_ + +#include + +#ifndef __ASM +#define __ASM __asm /*!< asm keyword for GNU Compiler */ +#endif + +#ifndef __INLINE +#define __INLINE inline /*!< inline keyword for GNU Compiler */ +#endif + +#ifndef __ALWAYS_STATIC_INLINE +#define __ALWAYS_STATIC_INLINE __attribute__((always_inline)) static inline +#endif + +#ifndef __STATIC_INLINE +#define __STATIC_INLINE static inline +#endif + +#ifndef __NO_RETURN +#define __NO_RETURN __attribute__((__noreturn__)) +#endif + +#ifndef __USED +#define __USED __attribute__((used)) +#endif + +#ifndef __WEAK +#define __WEAK __attribute__((weak)) +#endif + +#ifndef __PACKED +#define __PACKED __attribute__((packed, aligned(1))) +#endif + +#ifndef __PACKED_STRUCT +#define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif + +#ifndef __PACKED_UNION +#define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif + +#if 0 +/* ########################### Core Function Access ########################### */ +/** \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_RegAccFunctions CSI Core Register Access Functions + @{ + */ +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by setting the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile("csrs mstatus, 8"); + __ASM volatile("li a0, 0x888"); + __ASM volatile("csrs mie, a0"); + +} + +/** + \brief Enable supervisor IRQ Interrupts + \details Enables IRQ interrupts by setting the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_supervisor_irq(void) +{ + __ASM volatile("csrs sstatus, 2"); + __ASM volatile("li a0, 0x222"); + __ASM volatile("csrs sie, a0"); +} + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by clearing the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile("csrc mstatus, 8"); +} + +/** + \brief Disable supervisor IRQ Interrupts + \details Disables supervisor IRQ interrupts by clearing the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_supervisor_irq(void) +{ + __ASM volatile("csrc sstatus, 2"); +} + +/** + \brief Get MXSTATUS + \details Returns the content of the MXSTATUS Register. + \return MXSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MXSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mxstatus" : "=r"(result)); + return (result); +} + +/** + \brief Get SXSTATUS + \details Returns the content of the SXSTATUS Register. + \return SXSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SXSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, sxstatus" : "=r"(result)); + return (result); +} + +/** + \brief Get CPU WORK MODE + \details Returns CPU WORK MODE. + \return CPU WORK MODE + */ +__ALWAYS_STATIC_INLINE unsigned long __get_CPU_WORK_MODE(void) +{ + unsigned long result; + __ASM volatile("csrr %0, sxstatus" : "=r"(result)); + return ((result >> 30U) & 0x3U); +} + +/** + \brief Get SATP + \details Returns the content of the SATP Register. + \return SATP Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SATP(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, satp" : "=r"(result)); + return (result); +} + +/** + \brief Set SATP + \details Writes the given value to the SATP Register. + \param [in] satp SATP Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_SATP(unsigned long satp) +{ + __ASM volatile("csrw satp, %0" : : "r"(satp)); +} + +/** + \brief Set MEPC + \details Writes the given value to the MEPC Register. + \param [in] mstatus MEPC Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MEPC(unsigned long mepc) +{ + __ASM volatile("csrw mepc, %0" : : "r"(mepc)); +} + + +/** + \brief Set MXSTATUS + \details Writes the given value to the MXSTATUS Register. + \param [in] mxstatus MXSTATUS Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MXSTATUS(unsigned long mxstatus) +{ + __ASM volatile("csrw mxstatus, %0" : : "r"(mxstatus)); +} + +/** + \brief Get MSTATUS + \details Returns the content of the MSTATUS Register. + \return MSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mstatus" : "=r"(result)); + return (result); +} + +/** + \brief Set MSTATUS + \details Writes the given value to the MSTATUS Register. + \param [in] mstatus MSTATUS Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSTATUS(unsigned long mstatus) +{ + __ASM volatile("csrw mstatus, %0" : : "r"(mstatus)); +} + +/** + \brief Get MCOR + \details Returns the content of the MCOR Register. + \return MCOR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCOR(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mcor" : "=r"(result)); + return (result); +} + +/** + \brief Set MCOR + \details Writes the given value to the MCOR Register. + \param [in] mstatus MCOR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCOR(unsigned long mcor) +{ + __ASM volatile("csrw mcor, %0" : : "r"(mcor)); +} + +/** + \brief Get MHCR + \details Returns the content of the MHCR Register. + \return MHCR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHCR(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mhcr" : "=r"(result)); + return (result); +} + +/** + \brief Set MHCR + \details Writes the given value to the MHCR Register. + \param [in] mstatus MHCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MHCR(unsigned long mhcr) +{ + __ASM volatile("csrw mhcr, %0" : : "r"(mhcr)); +} + +/** + \brief Get MHINT + \details Returns the content of the MHINT Register. + \return MHINT Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHINT(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mhint" : "=r"(result)); + return (result); +} + +/** + \brief Set MHINT + \details Writes the given value to the MHINT Register. + \param [in] mstatus MHINT Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MHINT(unsigned long mhint) +{ + __ASM volatile("csrw mhint, %0" : : "r"(mhint)); +} + +/** + \brief Get MCCR2 + \details Returns the content of the MCCR2 Register. + \return MCCR2 Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCCR2(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mccr2" : "=r"(result)); + return (result); +} + +/** + \brief Set MCCR2 + \details Writes the given value to the MCCR2 Register. + \param [in] mstatus MCCR2 Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCCR2(unsigned long mccr2) +{ + __ASM volatile("csrw mccr2, %0" : : "r"(mccr2)); +} + +/** + \brief Get MISA Register + \details Returns the content of the MISA Register. + \return MISA Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MISA(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, misa" : "=r"(result)); + return (result); +} + +/** + \brief Set MISA + \details Writes the given value to the MISA Register. + \param [in] misa MISA Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MISA(unsigned long misa) +{ + __ASM volatile("csrw misa, %0" : : "r"(misa)); +} + +/** + \brief Get MIE Register + \details Returns the content of the MIE Register. + \return MIE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIE(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mie" : "=r"(result)); + return (result); +} + +/** + \brief Set MIE + \details Writes the given value to the MIE Register. + \param [in] mie MIE Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MIE(unsigned long mie) +{ + __ASM volatile("csrw mie, %0" : : "r"(mie)); +} + +/** + \brief Get MTVEC Register + \details Returns the content of the MTVEC Register. + \return MTVEC Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTVEC(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mtvec" : "=r"(result)); + return (result); +} + +/** + \brief Set MTVEC + \details Writes the given value to the MTVEC Register. + \param [in] mtvec MTVEC Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MTVEC(unsigned long mtvec) +{ + __ASM volatile("csrw mtvec, %0" : : "r"(mtvec)); +} + +/** + \brief Set MTVT + \details Writes the given value to the MTVT Register. + \param [in] mtvt MTVT Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MTVT(unsigned long mtvt) +{ + __ASM volatile("csrw mtvt, %0" : : "r"(mtvt)); +} + +/** + \brief Get MTVT Register + \details Returns the content of the MTVT Register. + \return MTVT Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTVT(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mtvt" : "=r"(result)); + return (result); +} + +/** + \brief Get SP + \details Returns the content of the SP Register. + \return SP Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SP(void) +{ + unsigned long result; + + __ASM volatile("mv %0, sp" : "=r"(result)); + return (result); +} + +/** + \brief Set SP + \details Writes the given value to the SP Register. + \param [in] sp SP Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_SP(unsigned long sp) +{ + __ASM volatile("mv sp, %0" : : "r"(sp): "sp"); +} + +/** + \brief Get MSCRATCH Register + \details Returns the content of the MSCRATCH Register. + \return MSCRATCH Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MSCRATCH(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mscratch" : "=r"(result)); + return (result); +} + +/** + \brief Set MSCRATCH + \details Writes the given value to the MSCRATCH Register. + \param [in] mscratch MSCRATCH Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSCRATCH(unsigned long mscratch) +{ + __ASM volatile("csrw mscratch, %0" : : "r"(mscratch)); +} + +/** + \brief Get MCAUSE Register + \details Returns the content of the MCAUSE Register. + \return MCAUSE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCAUSE(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mcause" : "=r"(result)); + return (result); +} + +/** + \brief Get SCAUSE Register + \details Returns the content of the SCAUSE Register. + \return SCAUSE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SCAUSE(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, scause" : "=r"(result)); + return (result); +} + +/** + \brief Get MNXTI Register + \details Returns the content of the MNXTI Register. + \return MNXTI Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MNXTI(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mnxti" : "=r"(result)); + return (result); +} + +/** + \brief Set MNXTI + \details Writes the given value to the MNXTI Register. + \param [in] mnxti MNXTI Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MNXTI(unsigned long mnxti) +{ + __ASM volatile("csrw mnxti, %0" : : "r"(mnxti)); +} + +/** + \brief Get MINTSTATUS Register + \details Returns the content of the MINTSTATUS Register. + \return MINTSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MINTSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mintstatus" : "=r"(result)); + return (result); +} + +/** + \brief Get MTVAL Register + \details Returns the content of the MTVAL Register. + \return MTVAL Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTVAL(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mtval" : "=r"(result)); + return (result); +} + +/** + \brief Get MIP Register + \details Returns the content of the MIP Register. + \return MIP Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIP(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mip" : "=r"(result)); + return (result); +} + +/** + \brief Set MIP + \details Writes the given value to the MIP Register. + \param [in] mip MIP Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MIP(unsigned long mip) +{ + __ASM volatile("csrw mip, %0" : : "r"(mip)); +} + +/** + \brief Get MCYCLEL Register + \details Returns the content of the MCYCLEL Register. + \return MCYCLE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCYCLE(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mcycle" : "=r"(result)); + return (result); +} + +/** + \brief Get MCYCLEH Register + \details Returns the content of the MCYCLEH Register. + \return MCYCLEH Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCYCLEH(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mcycleh" : "=r"(result)); + return (result); +} + +/** + \brief Get MINSTRET Register + \details Returns the content of the MINSTRET Register. + \return MINSTRET Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MINSTRET(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, minstret" : "=r"(result)); + return (result); +} + +/** + \brief Get MINSTRETH Register + \details Returns the content of the MINSTRETH Register. + \return MINSTRETH Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MINSTRETH(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, minstreth" : "=r"(result)); + return (result); +} + +/** + \brief Get MVENDORID Register + \details Returns the content of the MVENDROID Register. + \return MVENDORID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MVENDORID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mvendorid" : "=r"(result)); + return (result); +} + +/** + \brief Get MARCHID Register + \details Returns the content of the MARCHID Register. + \return MARCHID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MARCHID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, marchid" : "=r"(result)); + return (result); +} + +/** + \brief Get MIMPID Register + \details Returns the content of the MIMPID Register. + \return MIMPID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIMPID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mimpid" : "=r"(result)); + return (result); +} + +/** + \brief Get MHARTID Register + \details Returns the content of the MHARTID Register. + \return MHARTID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHARTID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mhartid" : "=r"(result)); + return (result); +} + +/** + \brief Get PMPCFGx Register + \details Returns the content of the PMPCFGx Register. + \return PMPCFGx Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG0(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg0" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG1(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg1" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG2(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg2" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG3(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg3" : "=r"(result)); + return (result); +} + +/** + \brief Get PMPxCFG Register by index + \details Returns the content of the PMPxCFG Register. + \param [in] idx PMP region index + \return PMPxCFG Register value + */ +__STATIC_INLINE uint8_t __get_PMPxCFG(unsigned long idx) +{ + unsigned long pmpcfgx = 0; + + if (idx < 4) { + pmpcfgx = __get_PMPCFG0(); + } else if (idx >= 4 && idx < 8) { + idx -= 4; + pmpcfgx = __get_PMPCFG1(); + } else if (idx >= 8 && idx < 12) { + idx -= 8; + pmpcfgx = __get_PMPCFG2(); + } else if (idx >= 12 && idx < 16) { + idx -= 12; + pmpcfgx = __get_PMPCFG3(); + } else { + return 0; + } + + return (uint8_t)((pmpcfgx & (0xFF << (idx << 3))) >> (idx << 3)); +} + +/** + \brief Set PMPCFGx + \details Writes the given value to the PMPCFGx Register. + \param [in] pmpcfg PMPCFGx Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_PMPCFG0(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg0, %0" : : "r"(pmpcfg)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPCFG1(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg1, %0" : : "r"(pmpcfg)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPCFG2(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg2, %0" : : "r"(pmpcfg)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPCFG3(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg3, %0" : : "r"(pmpcfg)); +} + +/** + \brief Set PMPxCFG by index + \details Writes the given value to the PMPxCFG Register. + \param [in] idx PMPx region index + \param [in] pmpxcfg PMPxCFG Register value to set + */ +__STATIC_INLINE void __set_PMPxCFG(unsigned long idx, uint8_t pmpxcfg) +{ + unsigned long pmpcfgx = 0; + + if (idx < 4) { + pmpcfgx = __get_PMPCFG0(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | ((unsigned long)(pmpxcfg) << (idx << 3)); + __set_PMPCFG0(pmpcfgx); + } else if (idx >= 4 && idx < 8) { + idx -= 4; + pmpcfgx = __get_PMPCFG1(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | ((unsigned long)(pmpxcfg) << (idx << 3)); + __set_PMPCFG1(pmpcfgx); + } else if (idx >= 8 && idx < 12) { + idx -= 8; + pmpcfgx = __get_PMPCFG2(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | ((unsigned long)(pmpxcfg) << (idx << 3)); + __set_PMPCFG2(pmpcfgx); + } else if (idx >= 12 && idx < 16) { + idx -= 12; + pmpcfgx = __get_PMPCFG3(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | ((unsigned long)(pmpxcfg) << (idx << 3)); + __set_PMPCFG3(pmpcfgx); + } else { + return; + } +} + +/** + \brief Get PMPADDRx Register + \details Returns the content of the PMPADDRx Register. + \return PMPADDRx Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR0(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr0" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR1(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr1" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR2(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr2" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR3(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr3" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR4(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr4" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR5(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr5" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR6(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr6" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR7(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr7" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR8(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr8" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR9(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr9" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR10(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr10" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR11(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr11" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR12(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr12" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR13(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr13" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR14(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr14" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR15(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr15" : "=r"(result)); + return (result); +} + +/** + \brief Get PMPADDRx Register by index + \details Returns the content of the PMPADDRx Register. + \param [in] idx PMP region index + \return PMPADDRx Register value + */ +__STATIC_INLINE unsigned long __get_PMPADDRx(unsigned long idx) +{ + switch (idx) { + case 0: + return __get_PMPADDR0(); + + case 1: + return __get_PMPADDR1(); + + case 2: + return __get_PMPADDR2(); + + case 3: + return __get_PMPADDR3(); + + case 4: + return __get_PMPADDR4(); + + case 5: + return __get_PMPADDR5(); + + case 6: + return __get_PMPADDR6(); + + case 7: + return __get_PMPADDR7(); + + case 8: + return __get_PMPADDR8(); + + case 9: + return __get_PMPADDR9(); + + case 10: + return __get_PMPADDR10(); + + case 11: + return __get_PMPADDR11(); + + case 12: + return __get_PMPADDR12(); + + case 13: + return __get_PMPADDR13(); + + case 14: + return __get_PMPADDR14(); + + case 15: + return __get_PMPADDR15(); + + default: + return 0; + } +} + +/** + \brief Set PMPADDRx + \details Writes the given value to the PMPADDRx Register. + \param [in] pmpaddr PMPADDRx Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_PMPADDR0(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr0, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR1(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr1, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR2(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr2, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR3(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr3, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR4(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr4, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR5(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr5, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR6(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr6, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR7(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr7, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR8(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr8, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR9(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr9, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR10(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr10, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR11(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr11, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR12(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr12, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR13(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr13, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR14(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr14, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR15(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr15, %0" : : "r"(pmpaddr)); +} + +/** + \brief Set PMPADDRx by index + \details Writes the given value to the PMPADDRx Register. + \param [in] idx PMP region index + \param [in] pmpaddr PMPADDRx Register value to set + */ +__STATIC_INLINE void __set_PMPADDRx(unsigned long idx, unsigned long pmpaddr) +{ + switch (idx) { + case 0: + __set_PMPADDR0(pmpaddr); + break; + + case 1: + __set_PMPADDR1(pmpaddr); + break; + + case 2: + __set_PMPADDR2(pmpaddr); + break; + + case 3: + __set_PMPADDR3(pmpaddr); + break; + + case 4: + __set_PMPADDR4(pmpaddr); + break; + + case 5: + __set_PMPADDR5(pmpaddr); + break; + + case 6: + __set_PMPADDR6(pmpaddr); + break; + + case 7: + __set_PMPADDR7(pmpaddr); + break; + + case 8: + __set_PMPADDR8(pmpaddr); + break; + + case 9: + __set_PMPADDR9(pmpaddr); + break; + + case 10: + __set_PMPADDR10(pmpaddr); + break; + + case 11: + __set_PMPADDR11(pmpaddr); + break; + + case 12: + __set_PMPADDR12(pmpaddr); + break; + + case 13: + __set_PMPADDR13(pmpaddr); + break; + + case 14: + __set_PMPADDR14(pmpaddr); + break; + + case 15: + __set_PMPADDR15(pmpaddr); + break; + + default: + return; + } +} + +/** + \brief Set MEDELEG Register + \details Writes the given value to the MEDELEG Register. + */ +__ALWAYS_STATIC_INLINE void __set_MEDELEG(unsigned long x) +{ + asm volatile("csrw medeleg, %0"::"r"(x)); +} + +/** + \brief Set MEDELEG Register + \details Writes the given value to the MEDELEG Register. + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MEDELEG(void) +{ + unsigned long x; + asm volatile("csrr %0, medeleg":"=r"(x)); + return x; +} + +/** + \brief Set MIDELEG Register + \details Writes the given value to the MIDELEG Register. + */ +__ALWAYS_STATIC_INLINE void __set_MIDELEG(unsigned long x) +{ + asm volatile("csrw mideleg, %0"::"r"(x)); +} + +/** + \brief Get MIDELEG Register + \details Returns the content of the MIDELEG Register. + \return MIDELEG Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIDELEG(void) +{ + unsigned long x; + asm volatile("csrr %0, mideleg":"=r"(x)); + return x; +} + +/** + \brief Set SSTATUS Register + \details Writes the given value to the SSTATUS Register. + */ +__ALWAYS_STATIC_INLINE void __set_SSTATUS(unsigned long x) +{ + asm volatile("csrw sstatus, %0"::"r"(x)); +} + +/** + \brief Get SSTATUS Register + \details Returns the content of the SSTATUS Register. + \return SSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SSTATUS(void) +{ + unsigned long x; + asm volatile("csrr %0, sstatus":"=r"(x)); + return x; +} + +/** + \brief Set SXSTATUS Register + \details Writes the given value to the SXSTATUS Register. + */ +__ALWAYS_STATIC_INLINE void __set_SXSTATUS(unsigned long x) +{ + asm volatile("csrw sxstatus, %0"::"r"(x)); +} + +/** + \brief Get SXSTATUS Register + \details Returns the content of the SXSTATUS Register. + \return SXSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get__SXSTATUS(void) +{ + unsigned long x; + asm volatile("csrr %0, sxstatus":"=r"(x)); + return x; +} + +/** + \brief Set SIE Register + \details Writes the given value to the SIE Register. + */ +__ALWAYS_STATIC_INLINE void __set_SIE(unsigned long x) +{ + asm volatile("csrw sie, %0"::"r"(x)); +} + +/** + \brief Get SIE Register + \details Returns the content of the SIE Register. + \return SIE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SIE(void) +{ + unsigned long x; + asm volatile("csrr %0, sie":"=r"(x)); + return x; +} + +/** + \brief Set STVAC Register + \details Writes the given value to the STVEC Register. + */ +__ALWAYS_STATIC_INLINE void __set_STVEC(unsigned long x) +{ + asm volatile("csrw stvec, %0"::"r"(x)); +} + +/** + \brief Get STVAC Register + \details Returns the content of the STVAC Register. + \return STVAC Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_STVEC(void) +{ + unsigned long x; + asm volatile("csrr %0, stvec":"=r"(x)); + return x; +} + +/** + \brief Enable interrupts and exceptions + \details Enables interrupts and exceptions by setting the IE-bit and EE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_excp_irq(void) +{ +#ifdef CONFIG_MMU + __enable_supervisor_irq(); +#else + __enable_irq(); +#endif +} + + +/** + \brief Disable interrupts and exceptions + \details Disables interrupts and exceptions by clearing the IE-bit and EE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_excp_irq(void) +{ +#ifdef CONFIG_MMU + __disable_supervisor_irq(); +#else + __disable_irq(); +#endif +} + +#define __CSI_GCC_OUT_REG(r) "=r" (r) +#define __CSI_GCC_USE_REG(r) "r" (r) + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__ALWAYS_STATIC_INLINE void __NOP(void) +{ + __ASM volatile("nop"); +} + + +/** + \brief return from M-MODE + \details return from M-MODE. + */ +__ALWAYS_STATIC_INLINE void __MRET(void) +{ + __ASM volatile("mret"); +} + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__ALWAYS_STATIC_INLINE void __WFI(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __WAIT(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Doze For Interrupt + \details Doze For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __DOZE(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Stop For Interrupt + \details Stop For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __STOP(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__ALWAYS_STATIC_INLINE void __ISB(void) +{ + __ASM volatile("fence"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__ALWAYS_STATIC_INLINE void __DSB(void) +{ + __ASM volatile("fence"); +} + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__ALWAYS_STATIC_INLINE void __SYNC_IS(void) +{ + __ASM volatile("sync.is"); +} + +/** + \brief Invalid all icache + \details invalid all icache. + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IALL(void) +{ + __ASM volatile("icache.iall"); +} + +/** + \brief Invalid all cpu icache + \details invalid all cpu icache. + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IALLS(void) +{ + __ASM volatile("icache.ialls"); +} + +/** + \brief Invalid Icache by phy addr + \details Invalid Icache by phy addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IPA(unsigned long addr) +{ + __ASM volatile("icache.ipa %0" : : "r"(addr)); +} + +/** + \brief Invalid Icache by virt address + \details Invalid Icache by virt address + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IVA(unsigned long addr) +{ + __ASM volatile("icache.iva %0" : : "r"(addr)); +} + +/** + \brief Invalid all dcache + \details invalid all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IALL(void) +{ + __ASM volatile("dcache.iall"); +} + +/** + \brief Clear all dcache + \details clear all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CALL(void) +{ + __ASM volatile("dcache.call"); +} + +/** + \brief Clear&invalid all dcache + \details clear & invalid all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIALL(void) +{ + __ASM volatile("dcache.ciall"); +} + +#if (__L2CACHE_PRESENT == 1U) +/** + \brief Invalid L2 cache + \details invalid L2 cache. + */ +__ALWAYS_STATIC_INLINE void __L2CACHE_IALL(void) +{ + __ASM volatile("l2cache.iall"); +} + +/** + \brief Clear L2cache + \details clear L2cache. + */ +__ALWAYS_STATIC_INLINE void __L2CACHE_CALL(void) +{ + __ASM volatile("l2cache.call"); +} + +/** + \brief Clear&invalid L2cache + \details clear & invalid L2cache. + */ +__ALWAYS_STATIC_INLINE void __L2CACHE_CIALL(void) +{ + __ASM volatile("l2cache.ciall"); +} +#endif + + +/** + \brief Invalid Dcache by addr + \details Invalid Dcache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IPA(unsigned long addr) +{ + __ASM volatile("dcache.ipa %0" : : "r"(addr)); +} + +/** + \brief Invalid Dcache by virt addr + \details Invalid Dcache by virt addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IVA(unsigned long addr) +{ + __ASM volatile("dcache.iva %0" : : "r"(addr)); +} + +/** + \brief Clear Dcache by addr + \details Clear Dcache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CPA(unsigned long addr) +{ + __ASM volatile("dcache.cpa %0" : : "r"(addr)); +} + +/** + \brief Clear Dcache by virt addr + \details Clear Dcache by virt addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CVA(unsigned long addr) +{ + __ASM volatile("dcache.cva %0" : : "r"(addr)); +} + +/** + \brief Clear & Invalid Dcache by addr + \details Clear & Invalid Dcache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIPA(unsigned long addr) +{ + __ASM volatile("dcache.cipa %0" : : "r"(addr)); +} + +/** + \brief Clear & Invalid Dcache by virt addr + \details Clear & Invalid Dcache by virt addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIVA(unsigned long addr) +{ + __ASM volatile("dcache.civa %0" : : "r"(addr)); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__ALWAYS_STATIC_INLINE void __DMB(void) +{ + __ASM volatile("fence"); +} + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE unsigned long __REV(unsigned long value) +{ + return __builtin_bswap32(value); +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + result = ((value & 0xFF000000) >> 8) | ((value & 0x00FF0000) << 8) | + ((value & 0x0000FF00) >> 8) | ((value & 0x000000FF) << 8); + + return (result); +} + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE int32_t __REVSH(int32_t value) +{ + return (short)(((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8)); +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__ALWAYS_STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + */ +__ALWAYS_STATIC_INLINE void __BKPT(void) +{ + __ASM volatile("ebreak"); +} + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + + for (value >>= 1U; value; value >>= 1U) { + result <<= 1U; + result |= value & 1U; + s--; + } + + result <<= s; /* shift when v's highest bits are zero */ + + return (result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz +/** + \details This function saturates a signed value. + \param [in] x Value to be saturated + \param [in] y Bit position to saturate to [1..32] + \return Saturated value. + */ +__ALWAYS_STATIC_INLINE int32_t __SSAT(int32_t x, uint32_t y) +{ + int32_t posMax, negMin; + uint32_t i; + + posMax = 1; + + for (i = 0; i < (y - 1); i++) { + posMax = posMax * 2; + } + + if (x > 0) { + posMax = (posMax - 1); + + if (x > posMax) { + x = posMax; + } + +// x &= (posMax * 2 + 1); + } else { + negMin = -posMax; + + if (x < negMin) { + x = negMin; + } + +// x &= (posMax * 2 - 1); + } + + return (x); +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__ALWAYS_STATIC_INLINE uint32_t __USAT(uint32_t value, uint32_t sat) +{ + uint32_t result; + + if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) { + result = 0xFFFFFFFF >> (32 - sat); + } else { + result = value; + } + + return (result); +} + +/** + \brief Unsigned Saturate for internal use + \details Saturates an unsigned value, should not call directly. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__ALWAYS_STATIC_INLINE uint32_t __IUSAT(uint32_t value, uint32_t sat) +{ + uint32_t result; + + if (value & 0x80000000) { /* only overflow set bit-31 */ + result = 0; + } else if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) { + result = 0xFFFFFFFF >> (32 - sat); + } else { + result = value; + } + + return (result); +} + +/** + \brief Rotate Right with Extend + \details This function moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \note carry input will always 0. + \param [in] op1 Value to rotate + \return Rotated value + */ +__ALWAYS_STATIC_INLINE uint32_t __RRX(uint32_t op1) +{ + return 0; +} + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] addr Pointer to location + \return value of type uint8_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile("lb %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] addr Pointer to location + \return value of type uint16_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile("lh %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] addr Pointer to location + \return value of type uint32_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile("lw %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return (result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) +{ + __ASM volatile("sb %1, 0(%0)" :: "r"(addr), "r"((uint32_t)value) : "memory"); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) +{ + __ASM volatile("sh %1, 0(%0)" :: "r"(addr), "r"((uint32_t)value) : "memory"); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) +{ + __ASM volatile("sw %1, 0(%0)" :: "r"(addr), "r"(value) : "memory"); +} + +/*@}*/ /* end of group CSI_Core_InstructionInterface */ + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CSI_SIMD_intrinsics CSI SIMD Intrinsics + Access to dedicated SIMD instructions \n + Single Instruction Multiple Data (SIMD) extensions are provided to simplify development of application software. SIMD extensions increase the processing capability without materially increasing the power consumption. The SIMD extensions are completely transparent to the operating system (OS), allowing existing OS ports to be used. + + @{ +*/ + +/** + \brief Halfword packing instruction. Combines bits[15:0] of val1 with bits[31:16] + of val2 levitated with the val3. + \details Combine a halfword from one register with a halfword from another register. + The second argument can be left-shifted before extraction of the halfword. + \param [in] val1 first 16-bit operands + \param [in] val2 second 16-bit operands + \param [in] val3 value for left-shifting val2. Value range [0..31]. + \return the combination of halfwords. + \remark + res[15:0] = val1[15:0] \n + res[31:16] = val2[31:16] << val3 + */ +__ALWAYS_STATIC_INLINE uint32_t __PKHBT(uint32_t val1, uint32_t val2, uint32_t val3) +{ + return ((((int32_t)(val1) << 0) & (int32_t)0x0000FFFF) | (((int32_t)(val2) << val3) & (int32_t)0xFFFF0000)); +} + +/** + \brief Halfword packing instruction. Combines bits[31:16] of val1 with bits[15:0] + of val2 right-shifted with the val3. + \details Combine a halfword from one register with a halfword from another register. + The second argument can be right-shifted before extraction of the halfword. + \param [in] val1 first 16-bit operands + \param [in] val2 second 16-bit operands + \param [in] val3 value for right-shifting val2. Value range [1..32]. + \return the combination of halfwords. + \remark + res[15:0] = val2[15:0] >> val3 \n + res[31:16] = val1[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __PKHTB(uint32_t val1, uint32_t val2, uint32_t val3) +{ + return ((((int32_t)(val1) << 0) & (int32_t)0xFFFF0000) | (((int32_t)(val2) >> val3) & (int32_t)0x0000FFFF)); +} + +/** + \brief Dual 16-bit signed saturate. + \details This function saturates a signed value. + \param [in] x two signed 16-bit values to be saturated. + \param [in] y bit position for saturation, an integral constant expression in the range 1 to 16. + \return the sum of the absolute differences of the following bytes, added to the accumulation value:\n + the signed saturation of the low halfword in val1, saturated to the bit position specified in + val2 and returned in the low halfword of the return value.\n + the signed saturation of the high halfword in val1, saturated to the bit position specified in + val2 and returned in the high halfword of the return value. + */ +__ALWAYS_STATIC_INLINE uint32_t __SSAT16(int32_t x, const uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __SSAT((((int32_t)x << 16) >> 16), y) & (int32_t)0x0000FFFF; + s = __SSAT((((int32_t)x) >> 16), y) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturate. + \details This function enables you to saturate two signed 16-bit values to a selected unsigned range. + \param [in] x two signed 16-bit values to be saturated. + \param [in] y bit position for saturation, an integral constant expression in the range 1 to 16. + \return the saturation of the two signed 16-bit values, as non-negative values: + the saturation of the low halfword in val1, saturated to the bit position specified in + val2 and returned in the low halfword of the return value.\n + the saturation of the high halfword in val1, saturated to the bit position specified in + val2 and returned in the high halfword of the return value. + */ +__ALWAYS_STATIC_INLINE uint32_t __USAT16(uint32_t x, const uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __IUSAT(((x << 16) >> 16), y) & 0x0000FFFF; + s = __IUSAT(((x) >> 16), y) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit saturating addition. + \details This function enables you to perform four 8-bit integer additions, + saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the saturated addition of the first byte of each operand in the first byte of the return value.\n + the saturated addition of the second byte of each operand in the second byte of the return value.\n + the saturated addition of the third byte of each operand in the third byte of the return value.\n + the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __QADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __SSAT(((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((int32_t)x) >> 24) + (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned saturating addition. + \details This function enables you to perform four unsigned 8-bit integer additions, + saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the saturated addition of the first byte of each operand in the first byte of the return value.\n + the saturated addition of the second byte of each operand in the second byte of the return value.\n + the saturated addition of the third byte of each operand in the third byte of the return value.\n + the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range 0 <= x <= 2^8 - 1. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __IUSAT((((x << 24) >> 24) + ((y << 24) >> 24)), 8) & 0x000000FF; + s = __IUSAT((((x << 16) >> 24) + ((y << 16) >> 24)), 8) & 0x000000FF; + t = __IUSAT((((x << 8) >> 24) + ((y << 8) >> 24)), 8) & 0x000000FF; + u = __IUSAT((((x) >> 24) + ((y) >> 24)), 8) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit signed addition. + \details This function performs four 8-bit signed integer additions. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the addition of the first bytes from each operand, in the first byte of the return value.\n + the addition of the second bytes of each operand, in the second byte of the return value.\n + the addition of the third bytes of each operand, in the third byte of the return value.\n + the addition of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __SADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF; + s = ((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF; + t = ((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)) & (int32_t)0x000000FF; + u = ((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned addition. + \details This function performs four unsigned 8-bit integer additions. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the addition of the first bytes from each operand, in the first byte of the return value.\n + the addition of the second bytes of each operand, in the second byte of the return value.\n + the addition of the third bytes of each operand, in the third byte of the return value.\n + the addition of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) + ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) + ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) + ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) + ((y) >> 24)) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit saturating subtract. + \details This function enables you to perform four 8-bit integer subtractions, + saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the subtraction of the first byte of each operand in the first byte of the return value.\n + the subtraction of the second byte of each operand in the second byte of the return value.\n + the subtraction of the third byte of each operand in the third byte of the return value.\n + the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __SSAT(((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((int32_t)x) >> 24) - (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned saturating subtraction. + \details This function enables you to perform four unsigned 8-bit integer subtractions, + saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the subtraction of the first byte of each operand in the first byte of the return value.\n + the subtraction of the second byte of each operand in the second byte of the return value.\n + the subtraction of the third byte of each operand in the third byte of the return value.\n + the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit unsigned integer range 0 <= x <= 2^8 - 1. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __IUSAT((((x << 24) >> 24) - ((y << 24) >> 24)), 8) & 0x000000FF; + s = __IUSAT((((x << 16) >> 24) - ((y << 16) >> 24)), 8) & 0x000000FF; + t = __IUSAT((((x << 8) >> 24) - ((y << 8) >> 24)), 8) & 0x000000FF; + u = __IUSAT((((x) >> 24) - ((y) >> 24)), 8) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit signed subtraction. + \details This function enables you to perform four 8-bit signed integer subtractions. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF; + s = ((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF; + t = ((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)) & (int32_t)0x000000FF; + u = ((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned subtract. + \details This function enables you to perform four 8-bit unsigned integer subtractions. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __USUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) - ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Unsigned sum of quad 8-bit unsigned absolute difference. + \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values + of the differences together, returning the result as a single unsigned integer. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value.\n + The sum is returned as a single unsigned integer. + \remark + absdiff1 = val1[7:0] - val2[7:0] \n + absdiff2 = val1[15:8] - val2[15:8] \n + absdiff3 = val1[23:16] - val2[23:16] \n + absdiff4 = val1[31:24] - val2[31:24] \n + res[31:0] = absdiff1 + absdiff2 + absdiff3 + absdiff4 + */ +__ALWAYS_STATIC_INLINE uint32_t __USAD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) - ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF; + + return (u + t + s + r); +} + +/** + \brief Unsigned sum of quad 8-bit unsigned absolute difference with 32-bit accumulate. + \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values + of the differences to a 32-bit accumulate operand. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \param [in] sum accumulation value. + \return the sum of the absolute differences of the following bytes, added to the accumulation value: + the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + absdiff1 = val1[7:0] - val2[7:0] \n + absdiff2 = val1[15:8] - val2[15:8] \n + absdiff3 = val1[23:16] - val2[23:16] \n + absdiff4 = val1[31:24] - val2[31:24] \n + sum = absdiff1 + absdiff2 + absdiff3 + absdiff4 \n + res[31:0] = sum[31:0] + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __USADA8(uint32_t x, uint32_t y, uint32_t sum) +{ + int32_t r, s, t, u; + +#ifdef __cplusplus + r = (abs((long long)((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF; + s = (abs((long long)((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF; + t = (abs((long long)((x << 8) >> 24) - ((y << 8) >> 24))) & 0x000000FF; + u = (abs((long long)((x) >> 24) - ((y) >> 24))) & 0x000000FF; +#else + r = (abs(((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF; + s = (abs(((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF; + t = (abs(((x << 8) >> 24) - ((y << 8) >> 24))) & 0x000000FF; + u = (abs(((x) >> 24) - ((y) >> 24))) & 0x000000FF; +#endif + return (u + t + s + r + sum); +} + +/** + \brief Dual 16-bit saturating addition. + \details This function enables you to perform two 16-bit integer arithmetic additions in parallel, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated addition of the low halfwords, in the low halfword of the return value.\n + the saturated addition of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __QADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating addition. + \details This function enables you to perform two unsigned 16-bit integer additions, saturating + the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated addition of the low halfwords, in the low halfword of the return value.\n + the saturated addition of the high halfwords, in the high halfword of the return value.\n + The results are saturated to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __IUSAT((((x << 16) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed addition. + \details This function enables you to perform two 16-bit signed integer additions. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the addition of the low halfwords in the low halfword of the return value.\n + the addition of the high halfwords in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __SADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = ((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition + \details This function enables you to perform two 16-bit unsigned integer additions. + \param [in] x first two 16-bit summands for each addition. + \param [in] y second two 16-bit summands for each addition. + \return the addition of the low halfwords in the low halfword of the return value.\n + the addition of the high halfwords in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = (((x << 16) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) + ((y) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + + +/** + \brief Dual 16-bit signed addition with halved results. + \details This function enables you to perform two signed 16-bit integer additions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved addition of the low halfwords, in the low halfword of the return value.\n + the halved addition of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] + val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHADD16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition with halved results. + \details This function enables you to perform two unsigned 16-bit integer additions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved addition of the low halfwords, in the low halfword of the return value.\n + the halved addition of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] + val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHADD16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit signed addition with halved results. + \details This function enables you to perform four signed 8-bit integer additions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved addition of the first bytes from each operand, in the first byte of the return value.\n + the halved addition of the second bytes from each operand, in the second byte of the return value.\n + the halved addition of the third bytes from each operand, in the third byte of the return value.\n + the halved addition of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] + val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] + val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] + val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] + val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF; + s = (((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF; + t = (((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)) >> 1) & (int32_t)0x000000FF; + u = (((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned addition with halved results. + \details This function enables you to perform four unsigned 8-bit integer additions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved addition of the first bytes from each operand, in the first byte of the return value.\n + the halved addition of the second bytes from each operand, in the second byte of the return value.\n + the halved addition of the third bytes from each operand, in the third byte of the return value.\n + the halved addition of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] + val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] + val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] + val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] + val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((x << 24) >> 24) + ((y << 24) >> 24)) >> 1) & 0x000000FF; + s = ((((x << 16) >> 24) + ((y << 16) >> 24)) >> 1) & 0x000000FF; + t = ((((x << 8) >> 24) + ((y << 8) >> 24)) >> 1) & 0x000000FF; + u = ((((x) >> 24) + ((y) >> 24)) >> 1) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Dual 16-bit saturating subtract. + \details This function enables you to perform two 16-bit integer subtractions in parallel, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated subtraction of the low halfwords, in the low halfword of the return value.\n + the saturated subtraction of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating subtraction. + \details This function enables you to perform two unsigned 16-bit integer subtractions, + saturating the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \param [in] x first two 16-bit operands for each subtraction. + \param [in] y second two 16-bit operands for each subtraction. + \return the saturated subtraction of the low halfwords, in the low halfword of the return value.\n + the saturated subtraction of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction. + \details This function enables you to perform two 16-bit signed integer subtractions. + \param [in] x first two 16-bit operands of each subtraction. + \param [in] y second two 16-bit operands of each subtraction. + \return the subtraction of the low halfword in the second operand from the low + halfword in the first operand, in the low halfword of the return value. \n + the subtraction of the high halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtract. + \details This function enables you to perform two 16-bit unsigned integer subtractions. + \param [in] x first two 16-bit operands of each subtraction. + \param [in] y second two 16-bit operands of each subtraction. + \return the subtraction of the low halfword in the second operand from the low + halfword in the first operand, in the low halfword of the return value. \n + the subtraction of the high halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __USUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) - ((y) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction with halved results. + \details This function enables you to perform two signed 16-bit integer subtractions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved subtraction of the low halfwords, in the low halfword of the return value.\n + the halved subtraction of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] - val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtraction with halved results. + \details This function enables you to perform two unsigned 16-bit integer subtractions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved subtraction of the low halfwords, in the low halfword of the return value.\n + the halved subtraction of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] - val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit signed addition with halved results. + \details This function enables you to perform four signed 8-bit integer subtractions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n + the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n + the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n + the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] - val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] - val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] - val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] - val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF; + s = (((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF; + t = (((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)) >> 1) & (int32_t)0x000000FF; + u = (((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned subtraction with halved results. + \details This function enables you to perform four unsigned 8-bit integer subtractions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n + the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n + the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n + the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] - val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] - val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] - val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] - val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((x << 24) >> 24) - ((y << 24) >> 24)) >> 1) & 0x000000FF; + s = ((((x << 16) >> 24) - ((y << 16) >> 24)) >> 1) & 0x000000FF; + t = ((((x << 8) >> 24) - ((y << 8) >> 24)) >> 1) & 0x000000FF; + u = ((((x) >> 24) - ((y) >> 24)) >> 1) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Dual 16-bit add and subtract with exchange. + \details This function enables you to exchange the halfwords of the one operand, + then add the high halfwords and subtract the low halfwords, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the saturated subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the saturated addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __QASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating addition and subtraction with exchange. + \details This function enables you to exchange the halfwords of the second operand and + perform one unsigned 16-bit integer addition and one unsigned 16-bit subtraction, + saturating the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the saturated subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the saturated addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit addition and subtraction with exchange. + \details It enables you to exchange the halfwords of the second operand, add the high halfwords + and subtract the low halfwords. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition and subtraction with exchange. + \details This function enables you to exchange the two halfwords of the second operand, + add the high halfwords and subtract the low halfwords. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) - ((y) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed addition and subtraction with halved results. + \details This function enables you to exchange the two halfwords of one operand, perform one + signed 16-bit integer addition and one signed 16-bit subtraction, and halve the results. + \param [in] x first 16-bit operands. + \param [in] y second 16-bit operands. + \return the halved subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the halved addition of the low halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] + val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition and subtraction with halved results and exchange. + \details This function enables you to exchange the halfwords of the second operand, + add the high halfwords and subtract the low halfwords, halving the results. + \param [in] x first operand for the subtraction in the low halfword, and + the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, and + the second operand for the addition in the low halfword. + \return the halved subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the halved addition of the low halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] + val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit subtract and add with exchange. + \details This function enables you to exchange the halfwords of one operand, + then subtract the high halfwords and add the low halfwords, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the saturated addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the saturated subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating subtraction and addition with exchange. + \details This function enables you to exchange the halfwords of the second operand and perform + one unsigned 16-bit integer subtraction and one unsigned 16-bit addition, saturating + the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the saturated addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the saturated subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit unsigned subtract and add with exchange. + \details This function enables you to exchange the halfwords of the second operand, + subtract the high halfwords and add the low halfwords. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __USAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) + ((y) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction and addition with exchange. + \details This function enables you to exchange the two halfwords of one operand and perform one + 16-bit integer subtraction and one 16-bit addition. + \param [in] x first operand for the addition in the low halfword, and the first operand + for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, and the second + operand for the subtraction in the low halfword. + \return the addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + + +/** + \brief Dual 16-bit signed subtraction and addition with halved results. + \details This function enables you to exchange the two halfwords of one operand, perform one signed + 16-bit integer subtraction and one signed 16-bit addition, and halve the results. + \param [in] x first 16-bit operands. + \param [in] y second 16-bit operands. + \return the halved addition of the low halfword in the first operand and the + high halfword in the second operand, in the low halfword of the return value.\n + the halved subtraction of the low halfword in the second operand from the + high halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] - val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtraction and addition with halved results and exchange. + \details This function enables you to exchange the halfwords of the second operand, + subtract the high halfwords and add the low halfwords, halving the results. + \param [in] x first operand for the addition in the low halfword, and + the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, and + the second operand for the subtraction in the low halfword. + \return the halved addition of the low halfword in the first operand and the + high halfword in the second operand, in the low halfword of the return value.\n + the halved subtraction of the low halfword in the second operand from the + high halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] - val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed multiply with exchange returning difference. + \details This function enables you to perform two 16-bit signed multiplications, subtracting + one of the products from the other. The halfwords of the second operand are exchanged + before performing the arithmetic. This produces top * bottom and bottom * top multiplication. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the difference of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 - p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUSDX(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)))); +} + +/** + \brief Sum of dual 16-bit signed multiply with exchange. + \details This function enables you to perform two 16-bit signed multiplications with exchanged + halfwords of the second operand, adding the products together. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the sum of the products of the two 16-bit signed multiplications with exchanged halfwords of the second operand. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 + p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUADX(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)))); +} + + +/** + \brief Saturating add. + \details This function enables you to obtain the saturating add of two integers. + \param [in] x first summand of the saturating add operation. + \param [in] y second summand of the saturating add operation. + \return the saturating addition of val1 and val2. + \remark + res[31:0] = SAT(val1 + SAT(val2)) + */ +__ALWAYS_STATIC_INLINE int32_t __QADD(int32_t x, int32_t y) +{ + int32_t result; + + if (y >= 0) { + if ((int32_t)((uint32_t)x + (uint32_t)y) >= x) { + result = x + y; + } else { + result = 0x7FFFFFFF; + } + } else { + if ((int32_t)((uint32_t)x + (uint32_t)y) < x) { + result = x + y; + } else { + result = 0x80000000; + } + } + + return result; +} + +/** + \brief Saturating subtract. + \details This function enables you to obtain the saturating add of two integers. + \param [in] x first summand of the saturating add operation. + \param [in] y second summand of the saturating add operation. + \return the saturating addition of val1 and val2. + \remark + res[31:0] = SAT(val1 - SAT(val2)) + */ +__ALWAYS_STATIC_INLINE int32_t __QSUB(int32_t x, int32_t y) +{ + long tmp; + int32_t result; + + tmp = (long)x - (long)y; + + if (tmp > 0x7fffffff) { + tmp = 0x7fffffff; + } else if (tmp < (-2147483647 - 1)) { + tmp = -2147483647 - 1; + } + + result = tmp; + return result; +} + +/** + \brief Dual 16-bit signed multiply with single 32-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications, + adding both results to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value, as a 32-bit integer. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 + p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLAD(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Pre-exchanged dual 16-bit signed multiply with single 32-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications with exchanged + halfwords of the second operand, adding both results to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication with exchanged halfwords of the second + operand added to the accumulate value, as a 32-bit integer. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 + p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLADX(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate. + \details This function enables you to perform two 16-bit signed multiplications, take the + difference of the products, subtracting the high halfword product from the low + halfword product, and add the difference to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 - p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLSD(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate. + \details This function enables you to exchange the halfwords in the second operand, then perform two 16-bit + signed multiplications. The difference of the products is added to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 - p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLSDX(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with single 64-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications, adding both results + to a 64-bit accumulate operand. Overflow is only possible as a result of the 64-bit addition. + This overflow is not detected if it occurs. Instead, the result wraps around modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + sum = p1 + p2 + val3[63:32][31:0] \n + res[63:32] = sum[63:32] \n + res[31:0] = sum[31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLALD(uint32_t x, uint32_t y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((unsigned long)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange with single 64-bit accumulator. + \details This function enables you to exchange the halfwords of the second operand, and perform two + signed 16-bit multiplications, adding both results to a 64-bit accumulate operand. Overflow + is only possible as a result of the 64-bit addition. This overflow is not detected if it occurs. + Instead, the result wraps around modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + sum = p1 + p2 + val3[63:32][31:0] \n + res[63:32] = sum[63:32] \n + res[31:0] = sum[31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLALDX(uint32_t x, uint32_t y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((unsigned long)sum)))); +} + +/** + \brief dual 16-bit signed multiply subtract with 64-bit accumulate. + \details This function It enables you to perform two 16-bit signed multiplications, take the difference + of the products, subtracting the high halfword product from the low halfword product, and add the + difference to a 64-bit accumulate operand. Overflow cannot occur during the multiplications or the + subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow is not + detected. Instead, the result wraps round to modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[63:32][31:0] = p1 - p2 + val3[63:32][31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLSLD(uint32_t x, uint32_t y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((unsigned long)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 64-bit accumulate. + \details This function enables you to exchange the halfwords of the second operand, perform two 16-bit multiplications, + adding the difference of the products to a 64-bit accumulate operand. Overflow cannot occur during the + multiplications or the subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow + is not detected. Instead, the result wraps round to modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[63:32][31:0] = p1 - p2 + val3[63:32][31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLSLDX(uint32_t x, uint32_t y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((unsigned long)sum)))); +} + +/** + \brief 32-bit signed multiply with 32-bit truncated accumulator. + \details This function enables you to perform a signed 32-bit multiplications, adding the most + significant 32 bits of the 64-bit result to a 32-bit accumulate operand. + \param [in] x first operand for multiplication. + \param [in] y second operand for multiplication. + \param [in] sum accumulate value. + \return the product of multiplication (most significant 32 bits) is added to the accumulate value, as a 32-bit integer. + \remark + p = val1 * val2 \n + res[31:0] = p[63:32] + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMMLA(int32_t x, int32_t y, int32_t sum) +{ + return (uint32_t)((int32_t)((long)((long)x * (long)y) >> 32) + sum); +} + +/** + \brief Sum of dual 16-bit signed multiply. + \details This function enables you to perform two 16-bit signed multiplications, adding the products together. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the sum of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 + p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUAD(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)))); +} + +/** + \brief Dual 16-bit signed multiply returning difference. + \details This function enables you to perform two 16-bit signed multiplications, taking the difference + of the products by subtracting the high halfword product from the low halfword product. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the difference of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 - p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUSD(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)))); +} + +/** + \brief Dual extracted 8-bit to 16-bit signed addition. + \details This function enables you to extract two 8-bit values from the second operand (at bit positions + [7:0] and [23:16]), sign-extend them to 16-bits each, and add the results to the first operand. + \param [in] x values added to the sign-extended to 16-bit values. + \param [in] y two 8-bit values to be extracted and sign-extended. + \return the addition of val1 and val2, where the 8-bit values in val2[7:0] and + val2[23:16] have been extracted and sign-extended prior to the addition. + \remark + res[15:0] = val1[15:0] + SignExtended(val2[7:0]) \n + res[31:16] = val1[31:16] + SignExtended(val2[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __SXTAB16(uint32_t x, uint32_t y) +{ + return ((uint32_t)((((((int32_t)y << 24) >> 24) + (((int32_t)x << 16) >> 16)) & (int32_t)0x0000FFFF) | + (((((int32_t)y << 8) >> 8) + (((int32_t)x >> 16) << 16)) & (int32_t)0xFFFF0000))); +} + +/** + \brief Extracted 16-bit to 32-bit unsigned addition. + \details This function enables you to extract two 8-bit values from one operand, zero-extend + them to 16 bits each, and add the results to two 16-bit values from another operand. + \param [in] x values added to the zero-extended to 16-bit values. + \param [in] y two 8-bit values to be extracted and zero-extended. + \return the addition of val1 and val2, where the 8-bit values in val2[7:0] and + val2[23:16] have been extracted and zero-extended prior to the addition. + \remark + res[15:0] = ZeroExt(val2[7:0] to 16 bits) + val1[15:0] \n + res[31:16] = ZeroExt(val2[31:16] to 16 bits) + val1[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UXTAB16(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((y << 24) >> 24) + ((x << 16) >> 16)) & 0x0000FFFF) | + ((((y << 8) >> 8) + ((x >> 16) << 16)) & 0xFFFF0000))); +} + +/** + \brief Dual extract 8-bits and sign extend each to 16-bits. + \details This function enables you to extract two 8-bit values from an operand and sign-extend them to 16 bits each. + \param [in] x two 8-bit values in val[7:0] and val[23:16] to be sign-extended. + \return the 8-bit values sign-extended to 16-bit values.\n + sign-extended value of val[7:0] in the low halfword of the return value.\n + sign-extended value of val[23:16] in the high halfword of the return value. + \remark + res[15:0] = SignExtended(val[7:0]) \n + res[31:16] = SignExtended(val[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __SXTB16(uint32_t x) +{ + return ((uint32_t)(((((int32_t)x << 24) >> 24) & (int32_t)0x0000FFFF) | + ((((int32_t)x << 8) >> 8) & (int32_t)0xFFFF0000))); +} + +/** + \brief Dual extract 8-bits and zero-extend to 16-bits. + \details This function enables you to extract two 8-bit values from an operand and zero-extend them to 16 bits each. + \param [in] x two 8-bit values in val[7:0] and val[23:16] to be zero-extended. + \return the 8-bit values sign-extended to 16-bit values.\n + sign-extended value of val[7:0] in the low halfword of the return value.\n + sign-extended value of val[23:16] in the high halfword of the return value. + \remark + res[15:0] = SignExtended(val[7:0]) \n + res[31:16] = SignExtended(val[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __UXTB16(uint32_t x) +{ + return ((uint32_t)((((x << 24) >> 24) & 0x0000FFFF) | + (((x << 8) >> 8) & 0xFFFF0000))); +} +#endif + +#endif /* _CSI_RV32_GCC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_gcc.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_gcc.h new file mode 100644 index 00000000000..75b42742655 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_gcc.h @@ -0,0 +1,3293 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file csi_gcc.h + * @brief CSI Header File for GCC. + * @version V1.0 + * @date 02. June 2020 + ******************************************************************************/ + +#ifndef _CSI_GCC_H_ +#define _CSI_GCC_H_ + +#include +#include + +#ifndef __ASM +#define __ASM __asm /*!< asm keyword for GNU Compiler */ +#endif + +#ifndef __INLINE +#define __INLINE inline /*!< inline keyword for GNU Compiler */ +#endif + +#ifndef __ALWAYS_STATIC_INLINE +#define __ALWAYS_STATIC_INLINE __attribute__((always_inline)) static inline +#endif + +#ifndef __STATIC_INLINE +#define __STATIC_INLINE static inline +#endif + +#ifndef __NO_RETURN +#define __NO_RETURN __attribute__((__noreturn__)) +#endif + +#ifndef __USED +#define __USED __attribute__((used)) +#endif + +#ifndef __WEAK +#define __WEAK __attribute__((weak)) +#endif + +#ifndef __PACKED +#define __PACKED __attribute__((packed, aligned(1))) +#endif + +#ifndef __PACKED_STRUCT +#define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif + +#ifndef __PACKED_UNION +#define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_RegAccFunctions CSI Core Register Access Functions + @{ + */ +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by setting the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile("psrset ie"); +} + + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by clearing the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile("psrclr ie"); +} + +/** + \brief Get PSR + \details Returns the content of the PSR Register. + \return PSR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_PSR(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, psr" : "=r"(result) :: "memory"); + return (result); +} + +/** + \brief Set PSR + \details Writes the given value to the PSR Register. + \param [in] psr PSR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_PSR(uint32_t psr) +{ + __ASM volatile("mtcr %0, psr" : : "r"(psr) : "memory"); +} + +/** + \brief Get SP + \details Returns the content of the SP Register. + \return SP Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_SP(void) +{ + uint32_t result; + + __ASM volatile("mov %0, sp" : "=r"(result)); + return (result); +} + +/** + \brief Set SP + \details Writes the given value to the SP Register. + \param [in] sp SP Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_SP(uint32_t sp) +{ + __ASM volatile("mov sp, %0" : : "r"(sp): "sp"); +} + +/** + \brief Get Int SP + \details Returns the content of the Int SP Register. + \return Int SP Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_Int_SP(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, cr<15, 1>" : "=r"(result)); + return (result); +} + +/** + \brief Set Int SP + \details Writes the given value to the Int SP Register. + \param [in] sp Int SP Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_Int_SP(uint32_t sp) +{ + __ASM volatile("mtcr %0, cr<15, 1>" : : "r"(sp)); +} + +/** + \brief Get VBR Register + \details Returns the content of the VBR Register. + \return VBR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_VBR(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, vbr" : "=r"(result)); + return (result); +} + +/** + \brief Set VBR + \details Writes the given value to the VBR Register. + \param [in] vbr VBR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_VBR(uint32_t vbr) +{ + __ASM volatile("mtcr %0, vbr" : : "r"(vbr)); +} + +/** + \brief Get EPC Register + \details Returns the content of the EPC Register. + \return EPC Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_EPC(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, epc" : "=r"(result)); + return (result); +} + +/** + \brief Set EPC + \details Writes the given value to the EPC Register. + \param [in] epc EPC Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_EPC(uint32_t epc) +{ + __ASM volatile("mtcr %0, epc" : : "r"(epc)); +} + +/** + \brief Get EPSR + \details Returns the content of the EPSR Register. + \return EPSR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_EPSR(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, epsr" : "=r"(result)); + return (result); +} + +/** + \brief Set EPSR + \details Writes the given value to the EPSR Register. + \param [in] epsr EPSR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_EPSR(uint32_t epsr) +{ + __ASM volatile("mtcr %0, epsr" : : "r"(epsr)); +} + +/** + \brief Get CPUID Register + \details Returns the content of the CPUID Register. + \return CPUID Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_CPUID(void) +{ + uint32_t result; + +#ifdef __CK610 + __ASM volatile("mfcr %0, cr13" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<13, 0>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Get CCR + \details Returns the current value of the CCR. + \return CCR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_CCR(void) +{ + register uint32_t result; + +#ifdef __CK610 + __ASM volatile("mfcr %0, cr18\n" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<18, 0>\n" : "=r"(result)); +#endif + return (result); +} + + +/** + \brief Set CCR + \details Assigns the given value to the CCR. + \param [in] ccr CCR value to set + */ +__ALWAYS_STATIC_INLINE void __set_CCR(uint32_t ccr) +{ +#ifdef __CK610 + __ASM volatile("mtcr %0, cr18\n" : : "r"(ccr)); +#else + __ASM volatile("mtcr %0, cr<18, 0>\n" : : "r"(ccr)); +#endif +} + +/** + \brief Get CCR2 + \details Returns the current value of the CCR2. + \return CCR2 Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_CCR2(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<31, 0>\n" : "=r"(result)); + return (result); +} + +/** + \brief Set CCR2 + \details Assigns the given value to the CCR2. + \param [in] ccr2 CCR2 value to set + */ +__ALWAYS_STATIC_INLINE void __set_CCR2(uint32_t ccr2) +{ + __ASM volatile("mtcr %0, cr<31, 0>\n" : : "r"(ccr2)); +} + +/** + \brief Get DCSR + \details Returns the content of the DCSR Register. + \return DCSR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_DCSR(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("mfcr %0, cr14" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<14, 0>" : "=r"(result)); +#endif + return (result); +} + + +/** + \brief Set DCSR + \details Writes the given value to the DCSR Register. + \param [in] dcsr DCSR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_DCSR(uint32_t dcsr) +{ +#ifdef __CK610 + __ASM volatile("mtcr %0, cr14" : : "r"(dcsr)); +#else + __ASM volatile("mtcr %0, cr<14, 0>" : : "r"(dcsr)); +#endif +} + + +/** + \brief Get CFR + \details Returns the content of the CFR Register. + \return CFR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_CFR(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("mfcr %0, cr17" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<17, 0>" : "=r"(result)); +#endif + + return (result); +} + + +/** + \brief Set CFR + \details Writes the given value to the CFR Register. + \param [in] cfr CFR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_CFR(uint32_t cfr) +{ +#ifdef __CK610 + __ASM volatile("mtcr %0, cr17" : : "r"(cfr)); +#else + __ASM volatile("mtcr %0, cr<17, 0>" : : "r"(cfr)); +#endif +} + + +/** + \brief Get CIR + \details Returns the content of the CIR Register. + \return CIR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_CIR(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("mfcr %0, cr22" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<22, 0>" : "=r"(result)); +#endif + return (result); +} + + +/** + \brief Set CIR + \details Writes the given value to the CIR Register. + \param [in] cir CIR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_CIR(uint32_t cir) +{ +#ifdef __CK610 + __ASM volatile("mtcr %0, cr22" : : "r"(cir)); +#else + __ASM volatile("mtcr %0, cr<22, 0>" : : "r"(cir)); +#endif +} + +/** + \brief Get ERRLC + \details Returns the current value of the ERRLC. + \return ERRLC Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_ERRLC(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<6, 1>\n" : "=r"(result)); + return (result); +} + +/** + \brief Set ERRLC + \details Assigns the given value to the ERRLC. + \param [in] errlc ERRLC value to set + */ +__ALWAYS_STATIC_INLINE void __set_ERRLC(uint32_t errlc) +{ + __ASM volatile("mtcr %0, cr<6, 1>\n" : : "r"(errlc)); +} + +/** + \brief Get ERRADDR + \details Returns the current value of the ERRADDR. + \return ERRADDR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_ERRADDR(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<7, 1>\n" : "=r"(result)); + return (result); +} + +/** + \brief Set ERRADDR + \details Assigns the given value to the ERRADDR. + \param [in] erraddr ERRADDR value to set + */ +__ALWAYS_STATIC_INLINE void __set_ERRADDR(uint32_t erraddr) +{ + __ASM volatile("mtcr %0, cr<7, 1>\n" : : "r"(erraddr)); +} + +/** + \brief Get ERRSTS + \details Returns the current value of the ERRSTS. + \return ERRSTS Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_ERRSTS(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<8, 1>\n" : "=r"(result)); + return (result); +} + +/** + \brief Set ERRSTS + \details Assigns the given value to the ERRSTS. + \param [in] errsts ERRSTS value to set + */ +__ALWAYS_STATIC_INLINE void __set_ERRSTS(uint32_t errsts) +{ + __ASM volatile("mtcr %0, cr<8, 1>\n" : : "r"(errsts)); +} + +/** + \brief Get ERRINJCR + \details Returns the current value of the ERRINJCR. + \return ERRINJCR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_ERRINJCR(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<9, 1>\n" : "=r"(result)); + return (result); +} + +/** + \brief Set ERRINJCR + \details Assigns the given value to the ERRINJCR. + \param [in] errinjcr ERRINJCR value to set + */ +__ALWAYS_STATIC_INLINE void __set_ERRINJCR(uint32_t errinjcr) +{ + __ASM volatile("mtcr %0, cr<9, 1>\n" : : "r"(errinjcr)); +} + +/** + \brief Get ERRINJCNT + \details Returns the current value of the ERRINJCNT. + \return ERRINJCNT Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_ERRINJCNT(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<10, 1>\n" : "=r"(result)); + return (result); +} + +/** + \brief Set ERRINJCNT + \details Assigns the given value to the ERRINJCNT. + \param [in] errinjcnt ERRINJCNT value to set + */ +__ALWAYS_STATIC_INLINE void __set_ERRINJCNT(uint32_t errinjcnt) +{ + __ASM volatile("mtcr %0, cr<10, 1>\n" : : "r"(errinjcnt)); +} + +/** + \brief Get ITCMCR + \details Returns the content of the ITCMCR Register. + \return ITCMCR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_ITCMCR(void) +{ + uint32_t result; + __ASM volatile("mfcr %0, cr<22, 1>" : "=r"(result)); + return (result); +} + +/** + \brief Set ITCMCR + \details Writes the given value to the ITCMCR Register. + \param [in] itcmcr ITCMCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_ITCMCR(uint32_t itcmcr) +{ + __ASM volatile("mtcr %0, cr<22, 1>" : : "r"(itcmcr)); +} + +/** + \brief Get DTCMCR + \details Returns the content of the DTCMCR Register. + \return DTCMCR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_DTCMCR(void) +{ + uint32_t result; + __ASM volatile("mfcr %0, cr<23, 1>" : "=r"(result)); + return (result); +} + +/** + \brief Set DTCMCR + \details Writes the given value to the DTCMCR Register. + \param [in] dtcmcr DTCMCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_DTCMCR(uint32_t dtcmcr) +{ + __ASM volatile("mtcr %0, cr<23, 1>" : : "r"(dtcmcr)); +} + +/** + \brief Get CINDEX + \details Returns the current value of the CINDEX. + \return CINDEX Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_CINDEX(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<26, 1>\n" : "=r"(result)); + return (result); +} + +/** + \brief Set CINDEX + \details Assigns the given value to the CINDEX. + \param [in] cindex CINDEX value to set + */ +__ALWAYS_STATIC_INLINE void __set_CINDEX(uint32_t cindex) +{ + __ASM volatile("mtcr %0, cr<26, 1>\n" : : "r"(cindex)); +} + +/** + \brief Get CDATAx + \details Returns the current value of the CDATAx. + \return CDATAx Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_CDATA0(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<27, 1>\n" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_CDATA1(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<28, 1>\n" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE uint32_t __get_CDATA2(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<29, 1>\n" : "=r"(result)); + return (result); +} + +/** + \brief Set CDATAx + \details Assigns the given value to the CDATAx. + \param [in] cdata CDATAx value to set + */ +__ALWAYS_STATIC_INLINE void __set_CDATA0(uint32_t cdata) +{ + __ASM volatile("mtcr %0, cr<27, 1>\n" : : "r"(cdata)); +} + +__ALWAYS_STATIC_INLINE void __set_CDATA1(uint32_t cdata) +{ + __ASM volatile("mtcr %0, cr<28, 1>\n" : : "r"(cdata)); +} + +__ALWAYS_STATIC_INLINE void __set_CDATA2(uint32_t cdata) +{ + __ASM volatile("mtcr %0, cr<29, 1>\n" : : "r"(cdata)); +} + +/** + \brief Get CINS + \details Returns the current value of the CINS. + \return CINS Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_CINS(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<31, 1>\n" : "=r"(result)); + return (result); +} + +/** + \brief Set CINS + \details Assigns the given value to the CINS. + \param [in] cins CINS value to set + */ +__ALWAYS_STATIC_INLINE void __set_CINS(uint32_t cins) +{ + __ASM volatile("mtcr %0, cr<31, 1>\n" : : "r"(cins)); +} + +/** + \brief Get CAPR + \details Returns the current value of the CAPR. + \return CAPR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_CAPR(void) +{ + register uint32_t result; + +#ifdef __CK610 + __ASM volatile("mfcr %0, cr19\n" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<19, 0>\n" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set CAPR + \details Assigns the given value to the CAPR. + \param [in] capr CAPR value to set + */ +__ALWAYS_STATIC_INLINE void __set_CAPR(uint32_t capr) +{ +#ifdef __CK610 + __ASM volatile("mtcr %0, cr19\n" : : "r"(capr)); +#else + __ASM volatile("mtcr %0, cr<19, 0>\n" : : "r"(capr)); +#endif +} + +/** + \brief Get CAPR1 + \details Returns the current value of the CAPR1. + \return CAPR1 Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_CAPR1(void) +{ + register uint32_t result; + + __ASM volatile("mfcr %0, cr<16, 0>\n" : "=r"(result)); + return (result); +} + +/** + \brief Set CAPR1 + \details Assigns the given value to the CAPR1. + \param [in] capr1 CAPR1 value to set + */ +__ALWAYS_STATIC_INLINE void __set_CAPR1(uint32_t capr1) +{ + __ASM volatile("mtcr %0, cr<16, 0>\n" : : "r"(capr1)); +} + +/** + \brief Set PACR + \details Assigns the given value to the PACR. + + \param [in] pacr PACR value to set + */ +__ALWAYS_STATIC_INLINE void __set_PACR(uint32_t pacr) +{ +#ifdef __CK610 + __ASM volatile("mtcr %0, cr20\n" : : "r"(pacr)); +#else + __ASM volatile("mtcr %0, cr<20, 0>\n" : : "r"(pacr)); +#endif +} + + +/** + \brief Get PACR + \details Returns the current value of PACR. + \return PACR value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_PACR(void) +{ + uint32_t result; + +#ifdef __CK610 + __ASM volatile("mfcr %0, cr20" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<20, 0>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set PRSR + \details Assigns the given value to the PRSR. + + \param [in] prsr PRSR value to set + */ +__ALWAYS_STATIC_INLINE void __set_PRSR(uint32_t prsr) +{ +#ifdef __CK610 + __ASM volatile("mtcr %0, cr21\n" : : "r"(prsr)); +#else + __ASM volatile("mtcr %0, cr<21, 0>\n" : : "r"(prsr)); +#endif +} + +/** + \brief Get PRSR + \details Returns the current value of PRSR. + \return PRSR value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_PRSR(void) +{ + uint32_t result; + +#ifdef __CK610 + __ASM volatile("mfcr %0, cr21" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<21, 0>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set ATTR0 + \details Assigns the given value to the ATTR0. + + \param [in] attr0 ATTR0 value to set + */ +__ALWAYS_STATIC_INLINE void __set_ATTR0(uint32_t attr0) +{ + __ASM volatile("mtcr %0, cr<26, 0>\n" : : "r"(attr0)); +} + +/** + \brief Get ATTR0 + \details Returns the current value of ATTR0. + \return ATTR0 value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_ATTR0(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, cr<26, 0>" : "=r"(result)); + + return (result); +} + +/** + \brief Set ATTR1 + \details Assigns the given value to the ATTR1. + + \param [in] attr0 ATTR1 value to set + */ +__ALWAYS_STATIC_INLINE void __set_ATTR1(uint32_t attr1) +{ + __ASM volatile("mtcr %0, cr<27, 0>\n" : : "r"(attr1)); +} + +/** + \brief Get ATTR1 + \details Returns the current value of ATTR1. + \return ATTR1 value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_ATTR1(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, cr<27, 0>" : "=r"(result)); + + return (result); +} + +/** + \brief Get user sp + \details Returns the current value of user r14. + \return UR14 value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_UR14(void) +{ + uint32_t result; + +#ifdef __CK610 + __ASM volatile("mov %0, sp" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<14, 1>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set UR14 + \details Assigns the given value to the UR14. + \param [in] ur14 UR14 value to set + */ +__ALWAYS_STATIC_INLINE void __set_UR14(uint32_t ur14) +{ +#ifdef __CK610 + __ASM volatile("mov sp, %0" : "=r"(ur14)); +#else + __ASM volatile("mtcr %0, cr<14, 1>\n" : : "r"(ur14)); +#endif +} + +/** + \brief Get CHR Register + \details Returns the content of the CHR Register. + \return CHR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_CHR(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, cr<31, 0>\n" :"=r"(result)); + return (result); +} + +/** + \brief Set CHR + \details Assigns the given value to the CHR. + \param [in] chr CHR value to set + */ +__ALWAYS_STATIC_INLINE void __set_CHR(uint32_t chr) +{ + __ASM volatile("mtcr %0, cr<31, 0>\n" : : "r"(chr)); +} + +/** + \brief Get HINT + \details Returns the content of the HINT Register. + \return HINT Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_HINT(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("mfcr %0, cr<30, 0>" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<31, 0>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set HINT + \details Writes the given value to the HINT Register. + \param [in] hint HINT Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_HINT(uint32_t hint) +{ +#ifdef __CK610 + __ASM volatile("mtcr %0, cr<30, 0>" : "=r"(hint)); +#else + __ASM volatile("mtcr %0, cr<31, 0>" : : "r"(hint)); +#endif +} + +/** + \brief Get MIR + \details Returns the content of the MIR Register. + \return MIR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MIR(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cprcr %0, cpcr0" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<0, 15>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set MIR + \details Writes the given value to the MIR Register. + \param [in] mir MIR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MIR(uint32_t mir) +{ +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cpwcr %0, cpcr0" : : "b"(mir)); +#else + __ASM volatile("mtcr %0, cr<0, 15>" : : "r"(mir)); +#endif +} + + +/** + \brief Get MEL0 + \details Returns the content of the MEL0 Register. + \return MEL0 Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MEL0(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cprcr %0, cpcr2" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<2, 15>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set MEL0 + \details Writes the given value to the MEL0 Register. + \param [in] mel0 MEL0 Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MEL0(uint32_t mel0) +{ +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cpwcr %0, cpcr2" : : "b"(mel0)); +#else + __ASM volatile("mtcr %0, cr<2, 15>" : : "r"(mel0)); +#endif +} + + +/** + \brief Get MEL1 + \details Returns the content of the MEL1 Register. + \return MEL1 Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MEL1(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cprcr %0, cpcr3" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<3, 15>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set MEL1 + \details Writes the given value to the MEL1 Register. + \param [in] mel1 MEL1 Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MEL1(uint32_t mel1) +{ +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cpwcr %0, cpcr3" : : "b"(mel1)); +#else + __ASM volatile("mtcr %0, cr<3, 15>" : : "r"(mel1)); +#endif +} + + +/** + \brief Get MEH + \details Returns the content of the MEH Register. + \return MEH Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MEH(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cprcr %0, cpcr4" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<4, 15>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set MEH + \details Writes the given value to the MEH Register. + \param [in] meh MEH Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MEH(uint32_t meh) +{ +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cpwcr %0, cpcr4" : : "b"(meh)); +#else + __ASM volatile("mtcr %0, cr<4, 15>" : : "r"(meh)); +#endif +} + + +/** + \brief Get MPR + \details Returns the content of the MPR Register. + \return MPR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MPR(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cprcr %0, cpcr6" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<6, 15>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set MPR + \details Writes the given value to the MPR Register. + \param [in] mpr MPR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MPR(uint32_t mpr) +{ +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cpwcr %0, cpcr6" : : "b"(mpr)); +#else + __ASM volatile("mtcr %0, cr<6, 15>" : : "r"(mpr)); +#endif +} + + +/** + \brief Get MCIR + \details Returns the content of the MCIR Register. + \return MCIR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MCIR(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cprcr %0, cpcr8" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<8, 15>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set MCIR + \details Writes the given value to the MCIR Register. + \param [in] mcir MCIR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCIR(uint32_t mcir) +{ +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cpwcr %0, cpcr8" : : "b"(mcir)); +#else + __ASM volatile("mtcr %0, cr<8, 15>" : : "r"(mcir)); +#endif +} + + +/** + \brief Get MPGD + \details Returns the content of the MPGD Register. + \return MPGD Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MPGD(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cprcr %0, cpcr29" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<29, 15>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set MPGD + \details Writes the given value to the MPGD Register. + \param [in] mpgd MPGD Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MPGD(uint32_t mpgd) +{ +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cpwcr %0, cpcr29" : : "b"(mpgd)); +#else + __ASM volatile("mtcr %0, cr<29, 15>" : : "r"(mpgd)); +#endif +} + + +/** + \brief Get MSA0 + \details Returns the content of the MSA0 Register. + \return MSA0 Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MSA0(void) +{ + uint32_t result; +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cprcr %0, cpcr30" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<30, 15>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set MSA0 + \details Writes the given value to the MSA0 Register. + \param [in] msa0 MSA0 Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSA0(uint32_t msa0) +{ +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cpwcr %0, cpcr30" : : "b"(msa0)); +#else + __ASM volatile("mtcr %0, cr<30, 15>" : : "r"(msa0)); +#endif +} + + +/** + \brief Get MSA1 + \details Returns the content of the MSA1 Register. + \return MSA1 Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_MSA1(void) +{ + uint32_t result; + +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cprcr %0, cpcr31" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<31, 15>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set MSA1 + \details Writes the given value to the MSA1 Register. + \param [in] msa1 MSA1 Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSA1(uint32_t msa1) +{ +#ifdef __CK610 + __ASM volatile("cpseti 15"); + __ASM volatile("cpwcr %0, cpcr31" : : "b"(msa1)); +#else + __ASM volatile("mtcr %0, cr<31, 15>" : : "r"(msa1)); +#endif +} + + +/** + \brief Enable interrupts and exceptions + \details Enables interrupts and exceptions by setting the IE-bit and EE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_excp_irq(void) +{ + __ASM volatile("psrset ee, ie"); +} + + +/** + \brief Disable interrupts and exceptions + \details Disables interrupts and exceptions by clearing the IE-bit and EE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_excp_irq(void) +{ + __ASM volatile("psrclr ee, ie"); +} + +/** + \brief Get GSR + \details Returns the content of the GSR Register. + \return GSR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_GSR(void) +{ + uint32_t result; + +#ifdef __CK610 + __ASM volatile("mfcr %0, cr12" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<12, 0>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Get GCR + \details Returns the content of the GCR Register. + \return GCR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_GCR(void) +{ + uint32_t result; + +#ifdef __CK610 + __ASM volatile("mfcr %0, cr11" : "=r"(result)); +#else + __ASM volatile("mfcr %0, cr<11, 0>" : "=r"(result)); +#endif + return (result); +} + +/** + \brief Set GCR + \details Writes the given value to the GCR Register. + \param [in] gcr GCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_GCR(uint32_t gcr) +{ +#ifdef __CK610 + __ASM volatile("mtcr %0, cr11" : : "r"(gcr)); +#else + __ASM volatile("mtcr %0, cr<11, 0>" : : "r"(gcr)); +#endif +} + +/** + \brief Get WSSR + \details Returns the content of the WSSR Register, must be accessed in TEE + \return WSSR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_WSSR(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, cr<0, 3>" : "=r"(result)); + return (result); +} + +/** + \brief Get WRCR + \details Returns the content of the WRCR Register, must be accessed in TEE + \return WRCR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_WRCR(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, cr<1, 3>" : "=r"(result)); + return (result); +} + +/** + \brief Set WRCR + \details Writes the given value to the WRCR Register, must be accessed in TEE + \param [in] wrcr WRCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_WRCR(uint32_t wrcr) +{ + __ASM volatile("mtcr %0, cr<1, 3>" : : "r"(wrcr)); +} + +/** + \brief Get DCR + \details Returns the content of the DCR Register, must be accessed in TEE + \return DCR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_DCR(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, cr<8, 3>" : "=r"(result)); + return (result); +} + +/** + \brief Set DCR + \details Writes the given value to the DCR Register, must be accessed in TEE + \param [in] dcr DCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_DCR(uint32_t dcr) +{ + __ASM volatile("mtcr %0, cr<8, 3>" : : "r"(dcr)); +} + +/** + \brief Get PCR + \details Returns the content of the PCR Register, must be accessed in TEE + \return PCR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_PCR(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, cr<9, 3>" : "=r"(result)); + return (result); +} + +/** + \brief Set PCR + \details Writes the given value to the PCR Register, must be accessed in TEE + \param [in] pcr PCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_PCR(uint32_t pcr) +{ + __ASM volatile("mtcr %0, cr<9, 3>" : : "r"(pcr)); +} + +/** + \brief Get EBR + \details Returns the content of the EBR Register. + \return EBR Register value + */ +__ALWAYS_STATIC_INLINE uint32_t __get_EBR(void) +{ + uint32_t result; + + __ASM volatile("mfcr %0, cr<1, 1>" : "=r"(result)); + return (result); +} + +/** + \brief Set EBR + \details Writes the given value to the EBR Register. + \param [in] ebr EBR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_EBR(uint32_t ebr) +{ + __ASM volatile("mtcr %0, cr<1, 1>" : : "r"(ebr)); +} + +/*@} end of CSI_Core_RegAccFunctions */ + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CSI_Core_InstructionInterface CSI Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#define __CSI_GCC_OUT_REG(r) "=r" (r) +#define __CSI_GCC_USE_REG(r) "r" (r) + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__ALWAYS_STATIC_INLINE void __NOP(void) +{ + __ASM volatile("nop"); +} + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__ALWAYS_STATIC_INLINE void __WFI(void) +{ + __ASM volatile("wait"); +} + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __WAIT(void) +{ + __ASM volatile("wait"); +} + +/** + \brief Doze For Interrupt + \details Doze For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __DOZE(void) +{ + __ASM volatile("doze"); +} + +/** + \brief Stop For Interrupt + \details Stop For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __STOP(void) +{ + __ASM volatile("stop"); +} + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__ALWAYS_STATIC_INLINE void __ISB(void) +{ + __ASM volatile("sync"::: "memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__ALWAYS_STATIC_INLINE void __DSB(void) +{ + __ASM volatile("sync"::: "memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__ALWAYS_STATIC_INLINE void __DMB(void) +{ + __ASM volatile("sync"::: "memory"); +} + +/** + \brief Search from the highest bit that the very first bit which's value is 1. + \param [in] value Value to bit search. + \return if the highest bit' value is 1, return 0, and if lowest bit's value is 1, return 31, otherwise return 32. + */ +#if !defined(__CK610) || !(__CK80X == 1) +__ALWAYS_STATIC_INLINE uint32_t __FF0(uint32_t value) +{ + uint32_t ret; + + __ASM volatile("ff0 %0, %1" : "=r"(ret) : "r"(value)); + return ret; +} +#endif + +/** + \brief Search from the highest bit that the very first bit which's value is 0. + \param [in] value Value to bit search. + \return if the highest bit' value is 0, return 0, and if lowest bit's value is 0, return 31, otherwise return 32. + */ +#if !(__CK80X == 1) +__ALWAYS_STATIC_INLINE uint32_t __FF1(uint32_t value) +{ + uint32_t ret; +#if !defined (__CK610) + __ASM volatile("ff1 %0, %1" : "=r"(ret) : "r"(value)); +#else + ret = value; + __ASM volatile("ff1 %0" : "=r"(ret):); +#endif + return ret; +} +#endif + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE uint32_t __REV(uint32_t value) +{ + return __builtin_bswap32(value); +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; +#if (__CK80X >= 2) + __ASM volatile("revh %0, %1" : __CSI_GCC_OUT_REG(result) : __CSI_GCC_USE_REG(value)); +#else + result = ((value & 0xFF000000) >> 8) | ((value & 0x00FF0000) << 8) | + ((value & 0x0000FF00) >> 8) | ((value & 0x000000FF) << 8); +#endif + return (result); +} + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE int32_t __REVSH(int32_t value) +{ + return (short)(((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8)); +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__ALWAYS_STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + */ +__ALWAYS_STATIC_INLINE void __BKPT(void) +{ + __ASM volatile("bkpt"); +} + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if (__CK80X >= 0x03U) + __ASM volatile("brev %0, %1" : "=r"(result) : "r"(value)); +#else + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + + for (value >>= 1U; value; value >>= 1U) { + result <<= 1U; + result |= value & 1U; + s--; + } + + result <<= s; /* shift when v's highest bits are zero */ +#endif + return (result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz +/** + \details This function saturates a signed value. + \param [in] x Value to be saturated + \param [in] y Bit position to saturate to [1..32] + \return Saturated value. + */ +__ALWAYS_STATIC_INLINE int32_t __SSAT(int32_t x, uint32_t y) +{ + int32_t posMax, negMin; + uint32_t i; + + posMax = 1; + + for (i = 0; i < (y - 1); i++) { + posMax = posMax * 2; + } + + if (x > 0) { + posMax = (posMax - 1); + + if (x > posMax) { + x = posMax; + } + +// x &= (posMax * 2 + 1); + } else { + negMin = -posMax; + + if (x < negMin) { + x = negMin; + } + +// x &= (posMax * 2 - 1); + } + + return (x); +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__ALWAYS_STATIC_INLINE uint32_t __USAT(uint32_t value, uint32_t sat) +{ + uint32_t result; + + if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) { + result = 0xFFFFFFFF >> (32 - sat); + } else { + result = value; + } + + return (result); +} + +/** + \brief Unsigned Saturate for internal use + \details Saturates an unsigned value, should not call directly. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__ALWAYS_STATIC_INLINE uint32_t __IUSAT(uint32_t value, uint32_t sat) +{ + uint32_t result; + + if (value & 0x80000000) { /* only overflow set bit-31 */ + result = 0; + } else if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) { + result = 0xFFFFFFFF >> (32 - sat); + } else { + result = value; + } + + return (result); +} + +/** + \brief Rotate Right with Extend + \details This function moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \note carry input will always 0. + \param [in] op1 Value to rotate + \return Rotated value + */ +__ALWAYS_STATIC_INLINE uint32_t __RRX(uint32_t op1) +{ +#if (__CK80X >= 2) + uint32_t res = 0; + __ASM volatile("bgeni t0, 31\n\t" + "lsri %0, 1\n\t" + "movt %1, t0\n\t" + "or %1, %1, %0\n\t" + : "=r"(op1), "=r"(res): "0"(op1), "1"(res): "t0"); + return res; +#else + uint32_t res = 0; + __ASM volatile("movi r7, 0\n\t" + "bseti r7, 31\n\t" + "lsri %0, 1\n\t" + "bf 1f\n\t" + "mov %1, r7\n\t" + "1:\n\t" + "or %1, %1, %0\n\t" + : "=r"(op1), "=r"(res): "0"(op1), "1"(res): "r7"); + return res; +#endif +} + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] addr Pointer to location + \return value of type uint8_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) +{ + uint32_t result; +//#warning "__LDRBT" + __ASM volatile("ldb %0, (%1, 0)" : "=r"(result) : "r"(addr)); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] addr Pointer to location + \return value of type uint16_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) +{ + uint32_t result; + +//#warning "__LDRHT" + __ASM volatile("ldh %0, (%1, 0)" : "=r"(result) : "r"(addr)); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] addr Pointer to location + \return value of type uint32_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) +{ + uint32_t result; + +//#warning "__LDRT" + __ASM volatile("ldw %0, (%1, 0)" : "=r"(result) : "r"(addr)); + return (result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) +{ +//#warning "__STRBT" + __ASM volatile("stb %1, (%0, 0)" :: "r"(addr), "r"((uint32_t)value) : "memory"); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) +{ +//#warning "__STRHT" + __ASM volatile("sth %1, (%0, 0)" :: "r"(addr), "r"((uint32_t)value) : "memory"); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) +{ +//#warning "__STRT" + __ASM volatile("stw %1, (%0, 0)" :: "r"(addr), "r"(value) : "memory"); +} + +/*@}*/ /* end of group CSI_Core_InstructionInterface */ + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type, always 0. + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__ALWAYS_STATIC_INLINE uint32_t __get_FPUType(void) +{ +//FIXME: + return 0; +} + +/*@} end of CSI_Core_FpuFunctions */ + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CSI_SIMD_intrinsics CSI SIMD Intrinsics + Access to dedicated SIMD instructions \n + Single Instruction Multiple Data (SIMD) extensions are provided to simplify development of application software. SIMD extensions increase the processing capability without materially increasing the power consumption. The SIMD extensions are completely transparent to the operating system (OS), allowing existing OS ports to be used. + + @{ +*/ + +/** + \brief Halfword packing instruction. Combines bits[15:0] of val1 with bits[31:16] + of val2 levitated with the val3. + \details Combine a halfword from one register with a halfword from another register. + The second argument can be left-shifted before extraction of the halfword. + \param [in] val1 first 16-bit operands + \param [in] val2 second 16-bit operands + \param [in] val3 value for left-shifting val2. Value range [0..31]. + \return the combination of halfwords. + \remark + res[15:0] = val1[15:0] \n + res[31:16] = val2[31:16] << val3 + */ +__ALWAYS_STATIC_INLINE uint32_t __PKHBT(uint32_t val1, uint32_t val2, uint32_t val3) +{ + return ((((int32_t)(val1) << 0) & (int32_t)0x0000FFFF) | (((int32_t)(val2) << val3) & (int32_t)0xFFFF0000)); +} + +/** + \brief Halfword packing instruction. Combines bits[31:16] of val1 with bits[15:0] + of val2 right-shifted with the val3. + \details Combine a halfword from one register with a halfword from another register. + The second argument can be right-shifted before extraction of the halfword. + \param [in] val1 first 16-bit operands + \param [in] val2 second 16-bit operands + \param [in] val3 value for right-shifting val2. Value range [1..32]. + \return the combination of halfwords. + \remark + res[15:0] = val2[15:0] >> val3 \n + res[31:16] = val1[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __PKHTB(uint32_t val1, uint32_t val2, uint32_t val3) +{ + return ((((int32_t)(val1) << 0) & (int32_t)0xFFFF0000) | (((int32_t)(val2) >> val3) & (int32_t)0x0000FFFF)); +} + +/** + \brief Dual 16-bit signed saturate. + \details This function saturates a signed value. + \param [in] x two signed 16-bit values to be saturated. + \param [in] y bit position for saturation, an integral constant expression in the range 1 to 16. + \return the sum of the absolute differences of the following bytes, added to the accumulation value:\n + the signed saturation of the low halfword in val1, saturated to the bit position specified in + val2 and returned in the low halfword of the return value.\n + the signed saturation of the high halfword in val1, saturated to the bit position specified in + val2 and returned in the high halfword of the return value. + */ +__ALWAYS_STATIC_INLINE uint32_t __SSAT16(int32_t x, const uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __SSAT((((int32_t)x << 16) >> 16), y) & (int32_t)0x0000FFFF; + s = __SSAT((((int32_t)x) >> 16), y) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturate. + \details This function enables you to saturate two signed 16-bit values to a selected unsigned range. + \param [in] x two signed 16-bit values to be saturated. + \param [in] y bit position for saturation, an integral constant expression in the range 1 to 16. + \return the saturation of the two signed 16-bit values, as non-negative values: + the saturation of the low halfword in val1, saturated to the bit position specified in + val2 and returned in the low halfword of the return value.\n + the saturation of the high halfword in val1, saturated to the bit position specified in + val2 and returned in the high halfword of the return value. + */ +__ALWAYS_STATIC_INLINE uint32_t __USAT16(uint32_t x, const uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __IUSAT(((x << 16) >> 16), y) & 0x0000FFFF; + s = __IUSAT(((x) >> 16), y) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit saturating addition. + \details This function enables you to perform four 8-bit integer additions, + saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the saturated addition of the first byte of each operand in the first byte of the return value.\n + the saturated addition of the second byte of each operand in the second byte of the return value.\n + the saturated addition of the third byte of each operand in the third byte of the return value.\n + the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __QADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __SSAT(((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((int32_t)x) >> 24) + (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned saturating addition. + \details This function enables you to perform four unsigned 8-bit integer additions, + saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the saturated addition of the first byte of each operand in the first byte of the return value.\n + the saturated addition of the second byte of each operand in the second byte of the return value.\n + the saturated addition of the third byte of each operand in the third byte of the return value.\n + the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range 0 <= x <= 2^8 - 1. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __IUSAT((((x << 24) >> 24) + ((y << 24) >> 24)), 8) & 0x000000FF; + s = __IUSAT((((x << 16) >> 24) + ((y << 16) >> 24)), 8) & 0x000000FF; + t = __IUSAT((((x << 8) >> 24) + ((y << 8) >> 24)), 8) & 0x000000FF; + u = __IUSAT((((x) >> 24) + ((y) >> 24)), 8) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit signed addition. + \details This function performs four 8-bit signed integer additions. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the addition of the first bytes from each operand, in the first byte of the return value.\n + the addition of the second bytes of each operand, in the second byte of the return value.\n + the addition of the third bytes of each operand, in the third byte of the return value.\n + the addition of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __SADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF; + s = ((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF; + t = ((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)) & (int32_t)0x000000FF; + u = ((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned addition. + \details This function performs four unsigned 8-bit integer additions. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the addition of the first bytes from each operand, in the first byte of the return value.\n + the addition of the second bytes of each operand, in the second byte of the return value.\n + the addition of the third bytes of each operand, in the third byte of the return value.\n + the addition of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) + ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) + ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) + ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) + ((y) >> 24)) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit saturating subtract. + \details This function enables you to perform four 8-bit integer subtractions, + saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the subtraction of the first byte of each operand in the first byte of the return value.\n + the subtraction of the second byte of each operand in the second byte of the return value.\n + the subtraction of the third byte of each operand in the third byte of the return value.\n + the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __SSAT(((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((int32_t)x) >> 24) - (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned saturating subtraction. + \details This function enables you to perform four unsigned 8-bit integer subtractions, + saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the subtraction of the first byte of each operand in the first byte of the return value.\n + the subtraction of the second byte of each operand in the second byte of the return value.\n + the subtraction of the third byte of each operand in the third byte of the return value.\n + the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit unsigned integer range 0 <= x <= 2^8 - 1. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __IUSAT((((x << 24) >> 24) - ((y << 24) >> 24)), 8) & 0x000000FF; + s = __IUSAT((((x << 16) >> 24) - ((y << 16) >> 24)), 8) & 0x000000FF; + t = __IUSAT((((x << 8) >> 24) - ((y << 8) >> 24)), 8) & 0x000000FF; + u = __IUSAT((((x) >> 24) - ((y) >> 24)), 8) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit signed subtraction. + \details This function enables you to perform four 8-bit signed integer subtractions. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF; + s = ((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF; + t = ((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)) & (int32_t)0x000000FF; + u = ((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned subtract. + \details This function enables you to perform four 8-bit unsigned integer subtractions. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __USUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) - ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Unsigned sum of quad 8-bit unsigned absolute difference. + \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values + of the differences together, returning the result as a single unsigned integer. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value.\n + The sum is returned as a single unsigned integer. + \remark + absdiff1 = val1[7:0] - val2[7:0] \n + absdiff2 = val1[15:8] - val2[15:8] \n + absdiff3 = val1[23:16] - val2[23:16] \n + absdiff4 = val1[31:24] - val2[31:24] \n + res[31:0] = absdiff1 + absdiff2 + absdiff3 + absdiff4 + */ +__ALWAYS_STATIC_INLINE uint32_t __USAD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) - ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF; + + return (u + t + s + r); +} + +/** + \brief Unsigned sum of quad 8-bit unsigned absolute difference with 32-bit accumulate. + \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values + of the differences to a 32-bit accumulate operand. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \param [in] sum accumulation value. + \return the sum of the absolute differences of the following bytes, added to the accumulation value: + the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + absdiff1 = val1[7:0] - val2[7:0] \n + absdiff2 = val1[15:8] - val2[15:8] \n + absdiff3 = val1[23:16] - val2[23:16] \n + absdiff4 = val1[31:24] - val2[31:24] \n + sum = absdiff1 + absdiff2 + absdiff3 + absdiff4 \n + res[31:0] = sum[31:0] + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __USADA8(uint32_t x, uint32_t y, uint32_t sum) +{ + int32_t r, s, t, u; + +#ifdef __cplusplus + r = (abs((long long)((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF; + s = (abs((long long)((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF; + t = (abs((long long)((x << 8) >> 24) - ((y << 8) >> 24))) & 0x000000FF; + u = (abs((long long)((x) >> 24) - ((y) >> 24))) & 0x000000FF; +#else + r = (abs(((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF; + s = (abs(((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF; + t = (abs(((x << 8) >> 24) - ((y << 8) >> 24))) & 0x000000FF; + u = (abs(((x) >> 24) - ((y) >> 24))) & 0x000000FF; +#endif + return (u + t + s + r + sum); +} + +/** + \brief Dual 16-bit saturating addition. + \details This function enables you to perform two 16-bit integer arithmetic additions in parallel, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated addition of the low halfwords, in the low halfword of the return value.\n + the saturated addition of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __QADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating addition. + \details This function enables you to perform two unsigned 16-bit integer additions, saturating + the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated addition of the low halfwords, in the low halfword of the return value.\n + the saturated addition of the high halfwords, in the high halfword of the return value.\n + The results are saturated to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __IUSAT((((x << 16) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed addition. + \details This function enables you to perform two 16-bit signed integer additions. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the addition of the low halfwords in the low halfword of the return value.\n + the addition of the high halfwords in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __SADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = ((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition + \details This function enables you to perform two 16-bit unsigned integer additions. + \param [in] x first two 16-bit summands for each addition. + \param [in] y second two 16-bit summands for each addition. + \return the addition of the low halfwords in the low halfword of the return value.\n + the addition of the high halfwords in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = (((x << 16) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) + ((y) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + + +/** + \brief Dual 16-bit signed addition with halved results. + \details This function enables you to perform two signed 16-bit integer additions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved addition of the low halfwords, in the low halfword of the return value.\n + the halved addition of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] + val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHADD16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition with halved results. + \details This function enables you to perform two unsigned 16-bit integer additions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved addition of the low halfwords, in the low halfword of the return value.\n + the halved addition of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] + val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHADD16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit signed addition with halved results. + \details This function enables you to perform four signed 8-bit integer additions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved addition of the first bytes from each operand, in the first byte of the return value.\n + the halved addition of the second bytes from each operand, in the second byte of the return value.\n + the halved addition of the third bytes from each operand, in the third byte of the return value.\n + the halved addition of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] + val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] + val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] + val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] + val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF; + s = (((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF; + t = (((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)) >> 1) & (int32_t)0x000000FF; + u = (((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned addition with halved results. + \details This function enables you to perform four unsigned 8-bit integer additions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved addition of the first bytes from each operand, in the first byte of the return value.\n + the halved addition of the second bytes from each operand, in the second byte of the return value.\n + the halved addition of the third bytes from each operand, in the third byte of the return value.\n + the halved addition of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] + val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] + val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] + val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] + val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((x << 24) >> 24) + ((y << 24) >> 24)) >> 1) & 0x000000FF; + s = ((((x << 16) >> 24) + ((y << 16) >> 24)) >> 1) & 0x000000FF; + t = ((((x << 8) >> 24) + ((y << 8) >> 24)) >> 1) & 0x000000FF; + u = ((((x) >> 24) + ((y) >> 24)) >> 1) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Dual 16-bit saturating subtract. + \details This function enables you to perform two 16-bit integer subtractions in parallel, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated subtraction of the low halfwords, in the low halfword of the return value.\n + the saturated subtraction of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating subtraction. + \details This function enables you to perform two unsigned 16-bit integer subtractions, + saturating the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \param [in] x first two 16-bit operands for each subtraction. + \param [in] y second two 16-bit operands for each subtraction. + \return the saturated subtraction of the low halfwords, in the low halfword of the return value.\n + the saturated subtraction of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction. + \details This function enables you to perform two 16-bit signed integer subtractions. + \param [in] x first two 16-bit operands of each subtraction. + \param [in] y second two 16-bit operands of each subtraction. + \return the subtraction of the low halfword in the second operand from the low + halfword in the first operand, in the low halfword of the return value. \n + the subtraction of the high halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtract. + \details This function enables you to perform two 16-bit unsigned integer subtractions. + \param [in] x first two 16-bit operands of each subtraction. + \param [in] y second two 16-bit operands of each subtraction. + \return the subtraction of the low halfword in the second operand from the low + halfword in the first operand, in the low halfword of the return value. \n + the subtraction of the high halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __USUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) - ((y) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction with halved results. + \details This function enables you to perform two signed 16-bit integer subtractions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved subtraction of the low halfwords, in the low halfword of the return value.\n + the halved subtraction of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] - val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtraction with halved results. + \details This function enables you to perform two unsigned 16-bit integer subtractions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved subtraction of the low halfwords, in the low halfword of the return value.\n + the halved subtraction of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] - val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit signed addition with halved results. + \details This function enables you to perform four signed 8-bit integer subtractions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n + the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n + the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n + the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] - val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] - val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] - val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] - val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF; + s = (((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF; + t = (((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)) >> 1) & (int32_t)0x000000FF; + u = (((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned subtraction with halved results. + \details This function enables you to perform four unsigned 8-bit integer subtractions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n + the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n + the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n + the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] - val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] - val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] - val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] - val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((x << 24) >> 24) - ((y << 24) >> 24)) >> 1) & 0x000000FF; + s = ((((x << 16) >> 24) - ((y << 16) >> 24)) >> 1) & 0x000000FF; + t = ((((x << 8) >> 24) - ((y << 8) >> 24)) >> 1) & 0x000000FF; + u = ((((x) >> 24) - ((y) >> 24)) >> 1) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Dual 16-bit add and subtract with exchange. + \details This function enables you to exchange the halfwords of the one operand, + then add the high halfwords and subtract the low halfwords, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the saturated subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the saturated addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __QASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating addition and subtraction with exchange. + \details This function enables you to exchange the halfwords of the second operand and + perform one unsigned 16-bit integer addition and one unsigned 16-bit subtraction, + saturating the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the saturated subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the saturated addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit addition and subtraction with exchange. + \details It enables you to exchange the halfwords of the second operand, add the high halfwords + and subtract the low halfwords. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition and subtraction with exchange. + \details This function enables you to exchange the two halfwords of the second operand, + add the high halfwords and subtract the low halfwords. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) - ((y) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed addition and subtraction with halved results. + \details This function enables you to exchange the two halfwords of one operand, perform one + signed 16-bit integer addition and one signed 16-bit subtraction, and halve the results. + \param [in] x first 16-bit operands. + \param [in] y second 16-bit operands. + \return the halved subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the halved addition of the low halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] + val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition and subtraction with halved results and exchange. + \details This function enables you to exchange the halfwords of the second operand, + add the high halfwords and subtract the low halfwords, halving the results. + \param [in] x first operand for the subtraction in the low halfword, and + the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, and + the second operand for the addition in the low halfword. + \return the halved subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the halved addition of the low halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] + val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit subtract and add with exchange. + \details This function enables you to exchange the halfwords of one operand, + then subtract the high halfwords and add the low halfwords, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the saturated addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the saturated subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating subtraction and addition with exchange. + \details This function enables you to exchange the halfwords of the second operand and perform + one unsigned 16-bit integer subtraction and one unsigned 16-bit addition, saturating + the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the saturated addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the saturated subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit unsigned subtract and add with exchange. + \details This function enables you to exchange the halfwords of the second operand, + subtract the high halfwords and add the low halfwords. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __USAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) + ((y) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction and addition with exchange. + \details This function enables you to exchange the two halfwords of one operand and perform one + 16-bit integer subtraction and one 16-bit addition. + \param [in] x first operand for the addition in the low halfword, and the first operand + for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, and the second + operand for the subtraction in the low halfword. + \return the addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + + +/** + \brief Dual 16-bit signed subtraction and addition with halved results. + \details This function enables you to exchange the two halfwords of one operand, perform one signed + 16-bit integer subtraction and one signed 16-bit addition, and halve the results. + \param [in] x first 16-bit operands. + \param [in] y second 16-bit operands. + \return the halved addition of the low halfword in the first operand and the + high halfword in the second operand, in the low halfword of the return value.\n + the halved subtraction of the low halfword in the second operand from the + high halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] - val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtraction and addition with halved results and exchange. + \details This function enables you to exchange the halfwords of the second operand, + subtract the high halfwords and add the low halfwords, halving the results. + \param [in] x first operand for the addition in the low halfword, and + the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, and + the second operand for the subtraction in the low halfword. + \return the halved addition of the low halfword in the first operand and the + high halfword in the second operand, in the low halfword of the return value.\n + the halved subtraction of the low halfword in the second operand from the + high halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] - val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed multiply with exchange returning difference. + \details This function enables you to perform two 16-bit signed multiplications, subtracting + one of the products from the other. The halfwords of the second operand are exchanged + before performing the arithmetic. This produces top * bottom and bottom * top multiplication. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the difference of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 - p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUSDX(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)))); +} + +/** + \brief Sum of dual 16-bit signed multiply with exchange. + \details This function enables you to perform two 16-bit signed multiplications with exchanged + halfwords of the second operand, adding the products together. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the sum of the products of the two 16-bit signed multiplications with exchanged halfwords of the second operand. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 + p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUADX(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)))); +} + + +/** + \brief Saturating add. + \details This function enables you to obtain the saturating add of two integers. + \param [in] x first summand of the saturating add operation. + \param [in] y second summand of the saturating add operation. + \return the saturating addition of val1 and val2. + \remark + res[31:0] = SAT(val1 + SAT(val2)) + */ +__ALWAYS_STATIC_INLINE int32_t __QADD(int32_t x, int32_t y) +{ + int32_t result; + + if (y >= 0) { + if (x + y >= x) { + result = x + y; + } else { + result = 0x7FFFFFFF; + } + } else { + if (x + y < x) { + result = x + y; + } else { + result = 0x80000000; + } + } + + return result; +} + +/** + \brief Saturating subtract. + \details This function enables you to obtain the saturating add of two integers. + \param [in] x first summand of the saturating add operation. + \param [in] y second summand of the saturating add operation. + \return the saturating addition of val1 and val2. + \remark + res[31:0] = SAT(val1 - SAT(val2)) + */ +__ALWAYS_STATIC_INLINE int32_t __QSUB(int32_t x, int32_t y) +{ + int64_t tmp; + int32_t result; + + tmp = (int64_t)x - (int64_t)y; + + if (tmp > 0x7fffffff) { + tmp = 0x7fffffff; + } else if (tmp < (-2147483647 - 1)) { + tmp = -2147483647 - 1; + } + + result = tmp; + return result; +} + +/** + \brief Dual 16-bit signed multiply with single 32-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications, + adding both results to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value, as a 32-bit integer. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 + p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLAD(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Pre-exchanged dual 16-bit signed multiply with single 32-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications with exchanged + halfwords of the second operand, adding both results to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication with exchanged halfwords of the second + operand added to the accumulate value, as a 32-bit integer. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 + p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLADX(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate. + \details This function enables you to perform two 16-bit signed multiplications, take the + difference of the products, subtracting the high halfword product from the low + halfword product, and add the difference to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 - p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLSD(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate. + \details This function enables you to exchange the halfwords in the second operand, then perform two 16-bit + signed multiplications. The difference of the products is added to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 - p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLSDX(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with single 64-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications, adding both results + to a 64-bit accumulate operand. Overflow is only possible as a result of the 64-bit addition. + This overflow is not detected if it occurs. Instead, the result wraps around modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + sum = p1 + p2 + val3[63:32][31:0] \n + res[63:32] = sum[63:32] \n + res[31:0] = sum[31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLALD(uint32_t x, uint32_t y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange with single 64-bit accumulator. + \details This function enables you to exchange the halfwords of the second operand, and perform two + signed 16-bit multiplications, adding both results to a 64-bit accumulate operand. Overflow + is only possible as a result of the 64-bit addition. This overflow is not detected if it occurs. + Instead, the result wraps around modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + sum = p1 + p2 + val3[63:32][31:0] \n + res[63:32] = sum[63:32] \n + res[31:0] = sum[31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLALDX(uint32_t x, uint32_t y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief dual 16-bit signed multiply subtract with 64-bit accumulate. + \details This function It enables you to perform two 16-bit signed multiplications, take the difference + of the products, subtracting the high halfword product from the low halfword product, and add the + difference to a 64-bit accumulate operand. Overflow cannot occur during the multiplications or the + subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow is not + detected. Instead, the result wraps round to modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[63:32][31:0] = p1 - p2 + val3[63:32][31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLSLD(uint32_t x, uint32_t y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 64-bit accumulate. + \details This function enables you to exchange the halfwords of the second operand, perform two 16-bit multiplications, + adding the difference of the products to a 64-bit accumulate operand. Overflow cannot occur during the + multiplications or the subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow + is not detected. Instead, the result wraps round to modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[63:32][31:0] = p1 - p2 + val3[63:32][31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLSLDX(uint32_t x, uint32_t y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief 32-bit signed multiply with 32-bit truncated accumulator. + \details This function enables you to perform a signed 32-bit multiplications, adding the most + significant 32 bits of the 64-bit result to a 32-bit accumulate operand. + \param [in] x first operand for multiplication. + \param [in] y second operand for multiplication. + \param [in] sum accumulate value. + \return the product of multiplication (most significant 32 bits) is added to the accumulate value, as a 32-bit integer. + \remark + p = val1 * val2 \n + res[31:0] = p[63:32] + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMMLA(int32_t x, int32_t y, int32_t sum) +{ + return (uint32_t)((int32_t)((int64_t)((int64_t)x * (int64_t)y) >> 32) + sum); +} + +/** + \brief Sum of dual 16-bit signed multiply. + \details This function enables you to perform two 16-bit signed multiplications, adding the products together. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the sum of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 + p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUAD(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)))); +} + +/** + \brief Dual 16-bit signed multiply returning difference. + \details This function enables you to perform two 16-bit signed multiplications, taking the difference + of the products by subtracting the high halfword product from the low halfword product. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the difference of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 - p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUSD(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)))); +} + +/** + \brief Dual extracted 8-bit to 16-bit signed addition. + \details This function enables you to extract two 8-bit values from the second operand (at bit positions + [7:0] and [23:16]), sign-extend them to 16-bits each, and add the results to the first operand. + \param [in] x values added to the sign-extended to 16-bit values. + \param [in] y two 8-bit values to be extracted and sign-extended. + \return the addition of val1 and val2, where the 8-bit values in val2[7:0] and + val2[23:16] have been extracted and sign-extended prior to the addition. + \remark + res[15:0] = val1[15:0] + SignExtended(val2[7:0]) \n + res[31:16] = val1[31:16] + SignExtended(val2[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __SXTAB16(uint32_t x, uint32_t y) +{ + return ((uint32_t)((((((int32_t)y << 24) >> 24) + (((int32_t)x << 16) >> 16)) & (int32_t)0x0000FFFF) | + (((((int32_t)y << 8) >> 8) + (((int32_t)x >> 16) << 16)) & (int32_t)0xFFFF0000))); +} + +/** + \brief Extracted 16-bit to 32-bit unsigned addition. + \details This function enables you to extract two 8-bit values from one operand, zero-extend + them to 16 bits each, and add the results to two 16-bit values from another operand. + \param [in] x values added to the zero-extended to 16-bit values. + \param [in] y two 8-bit values to be extracted and zero-extended. + \return the addition of val1 and val2, where the 8-bit values in val2[7:0] and + val2[23:16] have been extracted and zero-extended prior to the addition. + \remark + res[15:0] = ZeroExt(val2[7:0] to 16 bits) + val1[15:0] \n + res[31:16] = ZeroExt(val2[31:16] to 16 bits) + val1[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UXTAB16(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((y << 24) >> 24) + ((x << 16) >> 16)) & 0x0000FFFF) | + ((((y << 8) >> 8) + ((x >> 16) << 16)) & 0xFFFF0000))); +} + +/** + \brief Dual extract 8-bits and sign extend each to 16-bits. + \details This function enables you to extract two 8-bit values from an operand and sign-extend them to 16 bits each. + \param [in] x two 8-bit values in val[7:0] and val[23:16] to be sign-extended. + \return the 8-bit values sign-extended to 16-bit values.\n + sign-extended value of val[7:0] in the low halfword of the return value.\n + sign-extended value of val[23:16] in the high halfword of the return value. + \remark + res[15:0] = SignExtended(val[7:0]) \n + res[31:16] = SignExtended(val[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __SXTB16(uint32_t x) +{ + return ((uint32_t)(((((int32_t)x << 24) >> 24) & (int32_t)0x0000FFFF) | + ((((int32_t)x << 8) >> 8) & (int32_t)0xFFFF0000))); +} + +/** + \brief Dual extract 8-bits and zero-extend to 16-bits. + \details This function enables you to extract two 8-bit values from an operand and zero-extend them to 16 bits each. + \param [in] x two 8-bit values in val[7:0] and val[23:16] to be zero-extended. + \return the 8-bit values sign-extended to 16-bit values.\n + sign-extended value of val[7:0] in the low halfword of the return value.\n + sign-extended value of val[23:16] in the high halfword of the return value. + \remark + res[15:0] = SignExtended(val[7:0]) \n + res[31:16] = SignExtended(val[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __UXTB16(uint32_t x) +{ + return ((uint32_t)((((x << 24) >> 24) & 0x0000FFFF) | + (((x << 8) >> 8) & 0xFFFF0000))); +} + +#endif /* _CSI_GCC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv32_gcc.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv32_gcc.h new file mode 100644 index 00000000000..395a1aa9934 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv32_gcc.h @@ -0,0 +1,2935 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + + +/****************************************************************************** + * @file csi_rv32_gcc.h + * @brief CSI Header File for GCC. + * @version V1.0 + * @date 01. Sep 2018 + ******************************************************************************/ + +#ifndef _CSI_RV32_GCC_H_ +#define _CSI_RV32_GCC_H_ + +#include + +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP \ + || CONFIG_CPU_XUANTIE_E902 || CONFIG_CPU_XUANTIE_E902M || CONFIG_CPU_XUANTIE_E902T || CONFIG_CPU_XUANTIE_E902MT +#define CONFIG_CPU_XUANTIE_E9XX 1 +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_RegAccFunctions CSI Core Register Access Functions + @{ + */ +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by setting the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile("csrs mstatus, 8"); +} + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by clearing the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile("csrc mstatus, 8"); +} + +/** + \brief Get MXSTATUS + \details Returns the content of the MXSTATUS Register. + \return MXSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MXSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mxstatus" : "=r"(result)); + return (result); +} + +/** + \brief Set MXSTATUS + \details Writes the given value to the MXSTATUS Register. + \param [in] MXSTATUS Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MXSTATUS(unsigned long mxstatus) +{ + __ASM volatile("csrw mxstatus, %0" : : "r"(mxstatus)); +} + +/** + \brief Get MEXSTATUS + \details Returns the content of the MEXSTATUS Register. + \return MEXSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MEXSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mexstatus" : "=r"(result)); + return (result); +} + +/** + \brief Set MEXSTATUS + \details Writes the given value to the MSTATUS Register. + \param [in] MEXSTATUS Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MEXSTATUS(unsigned long mexstatus) +{ + __ASM volatile("csrw mexstatus, %0" : : "r"(mexstatus)); +} + + +/** + \brief Get MRADDR + \details Returns the content of the MRADDR Register. + \return MRADDR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MRADDR(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mraddr" : "=r"(result)); + return (result); +} + +/** + \brief Get FXCR + \details Returns the content of the FXCR Register. + \return FXCR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_FXCR(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, fxcr" : "=r"(result)); + return (result); +} + + +/** + \brief Set FXCR + \details Writes the given value to the FXCR Register. + \param [in] FXCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_FXCR(unsigned long fxcr) +{ + __ASM volatile("csrw fxcr, %0" : : "r"(fxcr)); +} + +/** + \brief Get MSTATUS + \details Returns the content of the MSTATUS Register. + \return MSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mstatus" : "=r"(result)); + return (result); +} + +/** + \brief Set MSTATUS + \details Writes the given value to the MSTATUS Register. + \param [in] mstatus MSTATUS Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSTATUS(unsigned long mstatus) +{ + __ASM volatile("csrw mstatus, %0" : : "r"(mstatus)); +} + +/** + \brief Get MHCR + \details Returns the content of the MHCR Register. + \return MHCR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHCR(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mhcr" : "=r"(result)); + return (result); +} + +/** + \brief Set MHCR + \details Writes the given value to the MHCR Register. + \param [in] MHCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MHCR(unsigned long mhcr) +{ + __ASM volatile("csrw mhcr, %0" : : "r"(mhcr)); +} + +/** + \brief Get MHINT + \details Returns the content of the MHINT Register. + \return MHINT Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHINT(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mhint" : "=r"(result)); + return (result); +} + +/** + \brief Set MHINT + \details Writes the given value to the MHINT Register. + \param [in] MHINT Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MHINT(unsigned long mhint) +{ + __ASM volatile("csrw mhint, %0" : : "r"(mhint)); +} + +/** + \brief Get MISA Register + \details Returns the content of the MISA Register. + \return MISA Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MISA(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, misa" : "=r"(result)); + return (result); +} + +/** + \brief Set MISA + \details Writes the given value to the MISA Register. + \param [in] misa MISA Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MISA(unsigned long misa) +{ + __ASM volatile("csrw misa, %0" : : "r"(misa)); +} + +/** + \brief Get MIE Register + \details Returns the content of the MIE Register. + \return MIE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIE(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mie" : "=r"(result)); + return (result); +} + +/** + \brief Set MIE + \details Writes the given value to the MIE Register. + \param [in] mie MIE Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MIE(unsigned long mie) +{ + __ASM volatile("csrw mie, %0" : : "r"(mie)); +} + +/** + \brief Get MTVEC Register + \details Returns the content of the MTVEC Register. + \return MTVEC Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTVEC(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mtvec" : "=r"(result)); + return (result); +} + +/** + \brief Set MTVEC + \details Writes the given value to the MTVEC Register. + \param [in] mtvec MTVEC Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MTVEC(unsigned long mtvec) +{ + __ASM volatile("csrw mtvec, %0" : : "r"(mtvec)); +} + +/** + \brief Set MTVT + \details Writes the given value to the MTVT Register. + \param [in] mtvt MTVT Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MTVT(unsigned long mtvt) +{ + __ASM volatile("csrw mtvt, %0" : : "r"(mtvt)); +} + +/** + \brief Get MTVT Register + \details Returns the content of the MTVT Register. + \return MTVT Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTVT(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mtvt" : "=r"(result)); + return (result); +} + +/** + \brief Get SP + \details Returns the content of the SP Register. + \return SP Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SP(void) +{ + unsigned long result; + + __ASM volatile("mv %0, sp" : "=r"(result)); + return (result); +} + +/** + \brief Set SP + \details Writes the given value to the SP Register. + \param [in] sp SP Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_SP(unsigned long sp) +{ + __ASM volatile("mv sp, %0" : : "r"(sp): "sp"); +} + +/** + \brief Get MSCRATCH Register + \details Returns the content of the MSCRATCH Register. + \return MSCRATCH Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MSCRATCH(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mscratch" : "=r"(result)); + return (result); +} + +/** + \brief Set MSCRATCH + \details Writes the given value to the MSCRATCH Register. + \param [in] mscratch MSCRATCH Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSCRATCH(unsigned long mscratch) +{ + __ASM volatile("csrw mscratch, %0" : : "r"(mscratch)); +} + +/** + \brief Get MEPC Register + \details Returns the content of the MEPC Register. + \return MEPC Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MEPC(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mepc" : "=r"(result)); + return (result); +} + +/** + \brief Set MEPC + \details Writes the given value to the MEPC Register. + \param [in] mepc MEPC Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MEPC(unsigned long mepc) +{ + __ASM volatile("csrw mepc, %0" : : "r"(mepc)); +} + +/** + \brief Get MCAUSE Register + \details Returns the content of the MCAUSE Register. + \return MCAUSE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCAUSE(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mcause" : "=r"(result)); + return (result); +} + +/** + \brief Get MNXTI Register + \details Returns the content of the MNXTI Register. + \return MNXTI Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MNXTI(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mnxti" : "=r"(result)); + return (result); +} + +/** + \brief Set MNXTI + \details Writes the given value to the MNXTI Register. + \param [in] mnxti MNXTI Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MNXTI(unsigned long mnxti) +{ + __ASM volatile("csrw mnxti, %0" : : "r"(mnxti)); +} + +/** + \brief Get MINTSTATUS Register + \details Returns the content of the MINTSTATUS Register. + \return MINTSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MINTSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mintstatus" : "=r"(result)); + return (result); +} + +/** + \brief Get MTVAL Register + \details Returns the content of the MTVAL Register. + \return MTVAL Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTVAL(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mtval" : "=r"(result)); + return (result); +} + +/** + \brief Get MIP Register + \details Returns the content of the MIP Register. + \return MIP Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIP(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mip" : "=r"(result)); + return (result); +} + +/** + \brief Set MIP + \details Writes the given value to the MIP Register. + \param [in] mip MIP Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MIP(unsigned long mip) +{ + __ASM volatile("csrw mip, %0" : : "r"(mip)); +} + +/** + \brief Get MCYCLEL Register + \details Returns the content of the MCYCLEL Register. + \return MCYCLE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCYCLE(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mcycle" : "=r"(result)); + return (result); +} + +/** + \brief Get MCYCLEH Register + \details Returns the content of the MCYCLEH Register. + \return MCYCLEH Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCYCLEH(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mcycleh" : "=r"(result)); + return (result); +} + +/** + \brief Get MINSTRET Register + \details Returns the content of the MINSTRET Register. + \return MINSTRET Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MINSTRET(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, minstret" : "=r"(result)); + return (result); +} + +/** + \brief Get MINSTRETH Register + \details Returns the content of the MINSTRETH Register. + \return MINSTRETH Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MINSTRETH(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, minstreth" : "=r"(result)); + return (result); +} + +#if (CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP) +/** + \brief Get MITCMCR + \details Returns the content of the MITCMCR Register. + \return MITCMCR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MITCMCR(void) +{ + unsigned long result; + __ASM volatile("csrr %0, mitcmcr" : "=r"(result)); + + return (result); +} + +/** + \brief Set MITCMCR + \details Writes the given value to the MITCMCR Register. + \param [in] itcmcr MITCMCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MITCMCR(unsigned long mitcmcr) +{ + __ASM volatile("csrw mitcmcr, %0" : : "r"(mitcmcr)); +} + +/** + \brief Get MDTCMCR + \details Returns the content of the MDTCMCR Register. + \return MDTCMCR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MDTCMCR(void) +{ + unsigned long result; + __ASM volatile("csrr %0, mdtcmcr" : "=r"(result)); + return (result); +} + +/** + \brief Set MDTCMCR + \details Writes the given value to the MDTCMCR Register. + \param [in] dtcmcr MDTCMCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MDTCMCR(unsigned long mdtcmcr) +{ + __ASM volatile("csrw mdtcmcr, %0" : : "r"(mdtcmcr)); +} +#endif /* end e907xx */ + + +/** + \brief Get MVENDORID Register + \details Returns the content of the MVENDROID Register. + \return MVENDORID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MVENDORID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mvendorid" : "=r"(result)); + return (result); +} + +/** + \brief Get MARCHID Register + \details Returns the content of the MARCHID Register. + \return MARCHID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MARCHID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, marchid" : "=r"(result)); + return (result); +} + +/** + \brief Get MIMPID Register + \details Returns the content of the MIMPID Register. + \return MIMPID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIMPID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mimpid" : "=r"(result)); + return (result); +} + +/** + \brief Get MHARTID Register + \details Returns the content of the MHARTID Register. + \return MHARTID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHARTID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mhartid" : "=r"(result)); + return (result); +} + +/** + \brief Get PMPCFGx Register + \details Returns the content of the PMPCFGx Register. + \return PMPCFGx Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG0(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg0" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG1(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg1" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG2(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg2" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG3(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg3" : "=r"(result)); + return (result); +} + +/** + \brief Get PMPxCFG Register by index + \details Returns the content of the PMPxCFG Register. + \param [in] idx PMP region index + \return PMPxCFG Register value + */ +__STATIC_INLINE uint8_t __get_PMPxCFG(unsigned long idx) +{ + unsigned long pmpcfgx = 0; + + if (idx < 4) { + pmpcfgx = __get_PMPCFG0(); + } else if (idx >=4 && idx < 8) { + idx -= 4; + pmpcfgx = __get_PMPCFG1(); + } else if (idx >=8 && idx < 12) { + idx -= 8; + pmpcfgx = __get_PMPCFG2(); + } else if (idx >=12 && idx < 16) { + idx -= 12; + pmpcfgx = __get_PMPCFG3(); + } else { + return 0; + } + + return (uint8_t)((pmpcfgx & (0xFF << (idx << 3))) >> (idx << 3)); +} + +/** + \brief Set PMPCFGx + \details Writes the given value to the PMPCFGx Register. + \param [in] pmpcfg PMPCFGx Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_PMPCFG0(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg0, %0" : : "r"(pmpcfg)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPCFG1(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg1, %0" : : "r"(pmpcfg)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPCFG2(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg2, %0" : : "r"(pmpcfg)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPCFG3(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg3, %0" : : "r"(pmpcfg)); +} + +/** + \brief Set PMPxCFG by index + \details Writes the given value to the PMPxCFG Register. + \param [in] idx PMPx region index + \param [in] pmpxcfg PMPxCFG Register value to set + */ +__STATIC_INLINE void __set_PMPxCFG(unsigned long idx, uint8_t pmpxcfg) +{ + unsigned long pmpcfgx = 0; + + if (idx < 4) { + pmpcfgx = __get_PMPCFG0(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3)); + __set_PMPCFG0(pmpcfgx); + } else if (idx >=4 && idx < 8) { + idx -= 4; + pmpcfgx = __get_PMPCFG1(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3)); + __set_PMPCFG1(pmpcfgx); + } else if (idx >=8 && idx < 12) { + idx -= 8; + pmpcfgx = __get_PMPCFG2(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3)); + __set_PMPCFG2(pmpcfgx); + } else if (idx >=12 && idx < 16) { + idx -= 12; + pmpcfgx = __get_PMPCFG3(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3)); + __set_PMPCFG3(pmpcfgx); + } else { + return; + } +} + +/** + \brief Get PMPADDRx Register + \details Returns the content of the PMPADDRx Register. + \return PMPADDRx Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR0(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr0" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR1(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr1" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR2(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr2" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR3(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr3" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR4(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr4" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR5(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr5" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR6(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr6" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR7(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr7" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR8(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr8" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR9(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr9" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR10(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr10" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR11(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr11" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR12(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr12" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR13(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr13" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR14(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr14" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR15(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr15" : "=r"(result)); + return (result); +} + +/** + \brief Get PMPADDRx Register by index + \details Returns the content of the PMPADDRx Register. + \param [in] idx PMP region index + \return PMPADDRx Register value + */ +__STATIC_INLINE unsigned long __get_PMPADDRx(unsigned long idx) +{ + switch (idx) { + case 0: return __get_PMPADDR0(); + case 1: return __get_PMPADDR1(); + case 2: return __get_PMPADDR2(); + case 3: return __get_PMPADDR3(); + case 4: return __get_PMPADDR4(); + case 5: return __get_PMPADDR5(); + case 6: return __get_PMPADDR6(); + case 7: return __get_PMPADDR7(); + case 8: return __get_PMPADDR8(); + case 9: return __get_PMPADDR9(); + case 10: return __get_PMPADDR10(); + case 11: return __get_PMPADDR11(); + case 12: return __get_PMPADDR12(); + case 13: return __get_PMPADDR13(); + case 14: return __get_PMPADDR14(); + case 15: return __get_PMPADDR15(); + default: return 0; + } +} + +/** + \brief Set PMPADDRx + \details Writes the given value to the PMPADDRx Register. + \param [in] pmpaddr PMPADDRx Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_PMPADDR0(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr0, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR1(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr1, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR2(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr2, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR3(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr3, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR4(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr4, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR5(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr5, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR6(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr6, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR7(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr7, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR8(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr8, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR9(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr9, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR10(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr10, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR11(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr11, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR12(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr12, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR13(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr13, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR14(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr14, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR15(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr15, %0" : : "r"(pmpaddr)); +} + +/** + \brief Set PMPADDRx by index + \details Writes the given value to the PMPADDRx Register. + \param [in] idx PMP region index + \param [in] pmpaddr PMPADDRx Register value to set + */ +__STATIC_INLINE void __set_PMPADDRx(unsigned long idx, unsigned long pmpaddr) +{ + switch (idx) { + case 0: __set_PMPADDR0(pmpaddr); break; + case 1: __set_PMPADDR1(pmpaddr); break; + case 2: __set_PMPADDR2(pmpaddr); break; + case 3: __set_PMPADDR3(pmpaddr); break; + case 4: __set_PMPADDR4(pmpaddr); break; + case 5: __set_PMPADDR5(pmpaddr); break; + case 6: __set_PMPADDR6(pmpaddr); break; + case 7: __set_PMPADDR7(pmpaddr); break; + case 8: __set_PMPADDR8(pmpaddr); break; + case 9: __set_PMPADDR9(pmpaddr); break; + case 10: __set_PMPADDR10(pmpaddr); break; + case 11: __set_PMPADDR11(pmpaddr); break; + case 12: __set_PMPADDR12(pmpaddr); break; + case 13: __set_PMPADDR13(pmpaddr); break; + case 14: __set_PMPADDR14(pmpaddr); break; + case 15: __set_PMPADDR15(pmpaddr); break; + default: return; + } +} + +/** + \brief Enable interrupts and exceptions + \details Enables interrupts and exceptions by setting the IE-bit and EE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_excp_irq(void) +{ + __enable_irq(); +} + +/** + \brief Disable interrupts and exceptions + \details Disables interrupts and exceptions by clearing the IE-bit and EE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_excp_irq(void) +{ + __disable_irq(); +} + +#define __CSI_GCC_OUT_REG(r) "=r" (r) +#define __CSI_GCC_USE_REG(r) "r" (r) + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__ALWAYS_STATIC_INLINE void __NOP(void) +{ + __ASM volatile("nop"); +} + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__ALWAYS_STATIC_INLINE void __WFI(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __WAIT(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Doze For Interrupt + \details Doze For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __DOZE(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Stop For Interrupt + \details Stop For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __STOP(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__ALWAYS_STATIC_INLINE void __ISB(void) +{ + __ASM volatile("fence.i"); + __ASM volatile("fence r, r"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__ALWAYS_STATIC_INLINE void __DSB(void) +{ + __ASM volatile("fence iorw, iorw"); +#ifndef __riscv_xtheadse + __ASM volatile("sync"); +#endif +} + +/** + \brief Invalid all icache + \details invalid all icache. + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IALL(void) +{ + __ASM volatile("icache.iall"); +} + +/** + \brief Invalid Icache by addr + \details Invalid Icache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IPA(unsigned long addr) +{ + __ASM volatile("icache.ipa %0" : : "r"(addr)); +} + +/** + \brief Invalid all dcache + \details invalid all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IALL(void) +{ +#ifndef __riscv_xtheadse + __ASM volatile("dcache.iall"); +#endif +} + +/** + \brief Clear all dcache + \details clear all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CALL(void) +{ +#ifndef __riscv_xtheadse + __ASM volatile("dcache.call"); +#endif +} + +/** + \brief Clear&invalid all dcache + \details clear & invalid all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIALL(void) +{ +#ifndef __riscv_xtheadse + __ASM volatile("dcache.ciall"); +#endif +} + +/** + \brief Invalid Dcache by addr + \details Invalid Dcache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IPA(unsigned long addr) +{ + __ASM volatile("dcache.ipa %0" : : "r"(addr)); +} + +/** + \brief Clear Dcache by addr + \details Clear Dcache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CPA(unsigned long addr) +{ + __ASM volatile("dcache.cpa %0" : : "r"(addr)); +} + +/** + \brief Clear & Invalid Dcache by addr + \details Clear & Invalid Dcache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIPA(unsigned long addr) +{ + __ASM volatile("dcache.cipa %0" : : "r"(addr)); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__ALWAYS_STATIC_INLINE void __DMB(void) +{ + __ASM volatile("fence"); +} + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE unsigned long __REV(unsigned long value) +{ + return __builtin_bswap32(value); +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE unsigned long __REV16(unsigned long value) +{ + unsigned long result; + + result = ((value & 0xFF000000) >> 8) | ((value & 0x00FF0000) << 8) | + ((value & 0x0000FF00) >> 8) | ((value & 0x000000FF) << 8); + + return (result); +} + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE int32_t __REVSH(int32_t value) +{ + return (short)(((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8)); +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__ALWAYS_STATIC_INLINE unsigned long __ROR(unsigned long op1, unsigned long op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + */ +__ALWAYS_STATIC_INLINE void __BKPT(void) +{ + __ASM volatile("ebreak"); +} + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE unsigned long __RBIT(unsigned long value) +{ + unsigned long result; + + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + + for (value >>= 1U; value; value >>= 1U) { + result <<= 1U; + result |= value & 1U; + s--; + } + + result <<= s; /* shift when v's highest bits are zero */ + + return (result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz +/** + \details This function saturates a signed value. + \param [in] x Value to be saturated + \param [in] y Bit position to saturate to [1..32] + \return Saturated value. + */ +__ALWAYS_STATIC_INLINE int32_t __SSAT(int32_t x, unsigned long y) +{ + int32_t posMax, negMin; + unsigned long i; + + posMax = 1; + + for (i = 0; i < (y - 1); i++) { + posMax = posMax * 2; + } + + if (x > 0) { + posMax = (posMax - 1); + + if (x > posMax) { + x = posMax; + } + +// x &= (posMax * 2 + 1); + } else { + negMin = -posMax; + + if (x < negMin) { + x = negMin; + } + +// x &= (posMax * 2 - 1); + } + + return (x); +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__ALWAYS_STATIC_INLINE unsigned long __USAT(unsigned long value, unsigned long sat) +{ + unsigned long result; + + if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) { + result = 0xFFFFFFFF >> (32 - sat); + } else { + result = value; + } + + return (result); +} + +/** + \brief Unsigned Saturate for internal use + \details Saturates an unsigned value, should not call directly. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__ALWAYS_STATIC_INLINE unsigned long __IUSAT(unsigned long value, unsigned long sat) +{ + unsigned long result; + + if (value & 0x80000000) { /* only overflow set bit-31 */ + result = 0; + } else if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) { + result = 0xFFFFFFFF >> (32 - sat); + } else { + result = value; + } + + return (result); +} + +/** + \brief Rotate Right with Extend + \details This function moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \note carry input will always 0. + \param [in] op1 Value to rotate + \return Rotated value + */ +__ALWAYS_STATIC_INLINE unsigned long __RRX(unsigned long op1) +{ + return 0; +} + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] addr Pointer to location + \return value of type uint8_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) +{ + unsigned long result; + + __ASM volatile("lb %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] addr Pointer to location + \return value of type uint16_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) +{ + unsigned long result; + + __ASM volatile("lh %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] addr Pointer to location + \return value of type unsigned long at (*ptr) + */ +__ALWAYS_STATIC_INLINE unsigned long __LDRT(volatile unsigned long *addr) +{ + unsigned long result; + + __ASM volatile("lw %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return (result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) +{ + __ASM volatile("sb %1, 0(%0)" :: "r"(addr), "r"((unsigned long)value) : "memory"); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) +{ + __ASM volatile("sh %1, 0(%0)" :: "r"(addr), "r"((unsigned long)value) : "memory"); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRT(unsigned long value, volatile unsigned long *addr) +{ + __ASM volatile("sw %1, 0(%0)" :: "r"(addr), "r"(value) : "memory"); +} + +/*@}*/ /* end of group CSI_Core_InstructionInterface */ + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CSI_SIMD_intrinsics CSI SIMD Intrinsics + Access to dedicated SIMD instructions \n + Single Instruction Multiple Data (SIMD) extensions are provided to simplify development of application software. SIMD extensions increase the processing capability without materially increasing the power consumption. The SIMD extensions are completely transparent to the operating system (OS), allowing existing OS ports to be used. + + @{ +*/ + +/** + \brief Halfword packing instruction. Combines bits[15:0] of val1 with bits[31:16] + of val2 levitated with the val3. + \details Combine a halfword from one register with a halfword from another register. + The second argument can be left-shifted before extraction of the halfword. + \param [in] val1 first 16-bit operands + \param [in] val2 second 16-bit operands + \param [in] val3 value for left-shifting val2. Value range [0..31]. + \return the combination of halfwords. + \remark + res[15:0] = val1[15:0] \n + res[31:16] = val2[31:16] << val3 + */ +__ALWAYS_STATIC_INLINE unsigned long __PKHBT(unsigned long val1, unsigned long val2, unsigned long val3) +{ + return ((((int32_t)(val1) << 0) & (int32_t)0x0000FFFF) | (((int32_t)(val2) << val3) & (int32_t)0xFFFF0000)); +} + +/** + \brief Halfword packing instruction. Combines bits[31:16] of val1 with bits[15:0] + of val2 right-shifted with the val3. + \details Combine a halfword from one register with a halfword from another register. + The second argument can be right-shifted before extraction of the halfword. + \param [in] val1 first 16-bit operands + \param [in] val2 second 16-bit operands + \param [in] val3 value for right-shifting val2. Value range [1..32]. + \return the combination of halfwords. + \remark + res[15:0] = val2[15:0] >> val3 \n + res[31:16] = val1[31:16] + */ +__ALWAYS_STATIC_INLINE unsigned long __PKHTB(unsigned long val1, unsigned long val2, unsigned long val3) +{ + return ((((int32_t)(val1) << 0) & (int32_t)0xFFFF0000) | (((int32_t)(val2) >> val3) & (int32_t)0x0000FFFF)); +} + +/** + \brief Dual 16-bit signed saturate. + \details This function saturates a signed value. + \param [in] x two signed 16-bit values to be saturated. + \param [in] y bit position for saturation, an integral constant expression in the range 1 to 16. + \return the sum of the absolute differences of the following bytes, added to the accumulation value:\n + the signed saturation of the low halfword in val1, saturated to the bit position specified in + val2 and returned in the low halfword of the return value.\n + the signed saturation of the high halfword in val1, saturated to the bit position specified in + val2 and returned in the high halfword of the return value. + */ +__ALWAYS_STATIC_INLINE unsigned long __SSAT16(int32_t x, const unsigned long y) +{ + int32_t r = 0, s = 0; + + r = __SSAT((((int32_t)x << 16) >> 16), y) & (int32_t)0x0000FFFF; + s = __SSAT((((int32_t)x) >> 16), y) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturate. + \details This function enables you to saturate two signed 16-bit values to a selected unsigned range. + \param [in] x two signed 16-bit values to be saturated. + \param [in] y bit position for saturation, an integral constant expression in the range 1 to 16. + \return the saturation of the two signed 16-bit values, as non-negative values: + the saturation of the low halfword in val1, saturated to the bit position specified in + val2 and returned in the low halfword of the return value.\n + the saturation of the high halfword in val1, saturated to the bit position specified in + val2 and returned in the high halfword of the return value. + */ +__ALWAYS_STATIC_INLINE unsigned long __USAT16(unsigned long x, const unsigned long y) +{ + int32_t r = 0, s = 0; + + r = __IUSAT(((x << 16) >> 16), y) & 0x0000FFFF; + s = __IUSAT(((x) >> 16), y) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit saturating addition. + \details This function enables you to perform four 8-bit integer additions, + saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the saturated addition of the first byte of each operand in the first byte of the return value.\n + the saturated addition of the second byte of each operand in the second byte of the return value.\n + the saturated addition of the third byte of each operand in the third byte of the return value.\n + the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE unsigned long __QADD8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = __SSAT(((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((int32_t)x) >> 24) + (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF; + + return ((unsigned long)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned saturating addition. + \details This function enables you to perform four unsigned 8-bit integer additions, + saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the saturated addition of the first byte of each operand in the first byte of the return value.\n + the saturated addition of the second byte of each operand in the second byte of the return value.\n + the saturated addition of the third byte of each operand in the third byte of the return value.\n + the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range 0 <= x <= 2^8 - 1. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE unsigned long __UQADD8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = __IUSAT((((x << 24) >> 24) + ((y << 24) >> 24)), 8) & 0x000000FF; + s = __IUSAT((((x << 16) >> 24) + ((y << 16) >> 24)), 8) & 0x000000FF; + t = __IUSAT((((x << 8) >> 24) + ((y << 8) >> 24)), 8) & 0x000000FF; + u = __IUSAT((((x) >> 24) + ((y) >> 24)), 8) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit signed addition. + \details This function performs four 8-bit signed integer additions. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the addition of the first bytes from each operand, in the first byte of the return value.\n + the addition of the second bytes of each operand, in the second byte of the return value.\n + the addition of the third bytes of each operand, in the third byte of the return value.\n + the addition of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE unsigned long __SADD8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = ((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF; + s = ((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF; + t = ((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)) & (int32_t)0x000000FF; + u = ((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) & (int32_t)0x000000FF; + + return ((unsigned long)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned addition. + \details This function performs four unsigned 8-bit integer additions. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the addition of the first bytes from each operand, in the first byte of the return value.\n + the addition of the second bytes of each operand, in the second byte of the return value.\n + the addition of the third bytes of each operand, in the third byte of the return value.\n + the addition of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE unsigned long __UADD8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) + ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) + ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) + ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) + ((y) >> 24)) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit saturating subtract. + \details This function enables you to perform four 8-bit integer subtractions, + saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the subtraction of the first byte of each operand in the first byte of the return value.\n + the subtraction of the second byte of each operand in the second byte of the return value.\n + the subtraction of the third byte of each operand in the third byte of the return value.\n + the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE unsigned long __QSUB8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = __SSAT(((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((int32_t)x) >> 24) - (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF; + + return ((unsigned long)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned saturating subtraction. + \details This function enables you to perform four unsigned 8-bit integer subtractions, + saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the subtraction of the first byte of each operand in the first byte of the return value.\n + the subtraction of the second byte of each operand in the second byte of the return value.\n + the subtraction of the third byte of each operand in the third byte of the return value.\n + the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit unsigned integer range 0 <= x <= 2^8 - 1. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE unsigned long __UQSUB8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = __IUSAT((((x << 24) >> 24) - ((y << 24) >> 24)), 8) & 0x000000FF; + s = __IUSAT((((x << 16) >> 24) - ((y << 16) >> 24)), 8) & 0x000000FF; + t = __IUSAT((((x << 8) >> 24) - ((y << 8) >> 24)), 8) & 0x000000FF; + u = __IUSAT((((x) >> 24) - ((y) >> 24)), 8) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit signed subtraction. + \details This function enables you to perform four 8-bit signed integer subtractions. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE unsigned long __SSUB8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = ((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF; + s = ((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF; + t = ((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)) & (int32_t)0x000000FF; + u = ((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) & (int32_t)0x000000FF; + + return ((unsigned long)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned subtract. + \details This function enables you to perform four 8-bit unsigned integer subtractions. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE unsigned long __USUB8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) - ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Unsigned sum of quad 8-bit unsigned absolute difference. + \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values + of the differences together, returning the result as a single unsigned integer. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value.\n + The sum is returned as a single unsigned integer. + \remark + absdiff1 = val1[7:0] - val2[7:0] \n + absdiff2 = val1[15:8] - val2[15:8] \n + absdiff3 = val1[23:16] - val2[23:16] \n + absdiff4 = val1[31:24] - val2[31:24] \n + res[31:0] = absdiff1 + absdiff2 + absdiff3 + absdiff4 + */ +__ALWAYS_STATIC_INLINE unsigned long __USAD8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) - ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF; + + return (u + t + s + r); +} + +/** + \brief Unsigned sum of quad 8-bit unsigned absolute difference with 32-bit accumulate. + \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values + of the differences to a 32-bit accumulate operand. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \param [in] sum accumulation value. + \return the sum of the absolute differences of the following bytes, added to the accumulation value: + the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + absdiff1 = val1[7:0] - val2[7:0] \n + absdiff2 = val1[15:8] - val2[15:8] \n + absdiff3 = val1[23:16] - val2[23:16] \n + absdiff4 = val1[31:24] - val2[31:24] \n + sum = absdiff1 + absdiff2 + absdiff3 + absdiff4 \n + res[31:0] = sum[31:0] + val3[31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __USADA8(unsigned long x, unsigned long y, unsigned long sum) +{ + int32_t r, s, t, u; + +#ifdef __cplusplus + r = (abs((long long)((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF; + s = (abs((long long)((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF; + t = (abs((long long)((x << 8) >> 24) - ((y << 8) >> 24))) & 0x000000FF; + u = (abs((long long)((x) >> 24) - ((y) >> 24))) & 0x000000FF; +#else + r = (abs(((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF; + s = (abs(((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF; + t = (abs(((x << 8) >> 24) - ((y << 8) >> 24))) & 0x000000FF; + u = (abs(((x) >> 24) - ((y) >> 24))) & 0x000000FF; +#endif + return (u + t + s + r + sum); +} + +/** + \brief Dual 16-bit saturating addition. + \details This function enables you to perform two 16-bit integer arithmetic additions in parallel, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated addition of the low halfwords, in the low halfword of the return value.\n + the saturated addition of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE unsigned long __QADD16(unsigned long x, unsigned long y) +{ + int32_t r = 0, s = 0; + + r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating addition. + \details This function enables you to perform two unsigned 16-bit integer additions, saturating + the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated addition of the low halfwords, in the low halfword of the return value.\n + the saturated addition of the high halfwords, in the high halfword of the return value.\n + The results are saturated to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE unsigned long __UQADD16(unsigned long x, unsigned long y) +{ + int32_t r = 0, s = 0; + + r = __IUSAT((((x << 16) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed addition. + \details This function enables you to perform two 16-bit signed integer additions. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the addition of the low halfwords in the low halfword of the return value.\n + the addition of the high halfwords in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE unsigned long __SADD16(unsigned long x, unsigned long y) +{ + int32_t r = 0, s = 0; + + r = ((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition + \details This function enables you to perform two 16-bit unsigned integer additions. + \param [in] x first two 16-bit summands for each addition. + \param [in] y second two 16-bit summands for each addition. + \return the addition of the low halfwords in the low halfword of the return value.\n + the addition of the high halfwords in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE unsigned long __UADD16(unsigned long x, unsigned long y) +{ + int32_t r = 0, s = 0; + + r = (((x << 16) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) + ((y) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + + +/** + \brief Dual 16-bit signed addition with halved results. + \details This function enables you to perform two signed 16-bit integer additions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved addition of the low halfwords, in the low halfword of the return value.\n + the halved addition of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] + val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __SHADD16(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition with halved results. + \details This function enables you to perform two unsigned 16-bit integer additions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved addition of the low halfwords, in the low halfword of the return value.\n + the halved addition of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] + val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __UHADD16(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit signed addition with halved results. + \details This function enables you to perform four signed 8-bit integer additions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved addition of the first bytes from each operand, in the first byte of the return value.\n + the halved addition of the second bytes from each operand, in the second byte of the return value.\n + the halved addition of the third bytes from each operand, in the third byte of the return value.\n + the halved addition of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] + val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] + val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] + val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] + val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __SHADD8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = (((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF; + s = (((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF; + t = (((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)) >> 1) & (int32_t)0x000000FF; + u = (((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF; + + return ((unsigned long)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned addition with halved results. + \details This function enables you to perform four unsigned 8-bit integer additions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved addition of the first bytes from each operand, in the first byte of the return value.\n + the halved addition of the second bytes from each operand, in the second byte of the return value.\n + the halved addition of the third bytes from each operand, in the third byte of the return value.\n + the halved addition of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] + val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] + val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] + val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] + val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __UHADD8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = ((((x << 24) >> 24) + ((y << 24) >> 24)) >> 1) & 0x000000FF; + s = ((((x << 16) >> 24) + ((y << 16) >> 24)) >> 1) & 0x000000FF; + t = ((((x << 8) >> 24) + ((y << 8) >> 24)) >> 1) & 0x000000FF; + u = ((((x) >> 24) + ((y) >> 24)) >> 1) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Dual 16-bit saturating subtract. + \details This function enables you to perform two 16-bit integer subtractions in parallel, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated subtraction of the low halfwords, in the low halfword of the return value.\n + the saturated subtraction of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE unsigned long __QSUB16(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating subtraction. + \details This function enables you to perform two unsigned 16-bit integer subtractions, + saturating the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \param [in] x first two 16-bit operands for each subtraction. + \param [in] y second two 16-bit operands for each subtraction. + \return the saturated subtraction of the low halfwords, in the low halfword of the return value.\n + the saturated subtraction of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE unsigned long __UQSUB16(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction. + \details This function enables you to perform two 16-bit signed integer subtractions. + \param [in] x first two 16-bit operands of each subtraction. + \param [in] y second two 16-bit operands of each subtraction. + \return the subtraction of the low halfword in the second operand from the low + halfword in the first operand, in the low halfword of the return value. \n + the subtraction of the high halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE unsigned long __SSUB16(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtract. + \details This function enables you to perform two 16-bit unsigned integer subtractions. + \param [in] x first two 16-bit operands of each subtraction. + \param [in] y second two 16-bit operands of each subtraction. + \return the subtraction of the low halfword in the second operand from the low + halfword in the first operand, in the low halfword of the return value. \n + the subtraction of the high halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE unsigned long __USUB16(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) - ((y) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction with halved results. + \details This function enables you to perform two signed 16-bit integer subtractions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved subtraction of the low halfwords, in the low halfword of the return value.\n + the halved subtraction of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] - val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __SHSUB16(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtraction with halved results. + \details This function enables you to perform two unsigned 16-bit integer subtractions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved subtraction of the low halfwords, in the low halfword of the return value.\n + the halved subtraction of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] - val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __UHSUB16(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit signed addition with halved results. + \details This function enables you to perform four signed 8-bit integer subtractions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n + the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n + the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n + the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] - val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] - val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] - val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] - val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __SHSUB8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = (((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF; + s = (((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF; + t = (((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)) >> 1) & (int32_t)0x000000FF; + u = (((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF; + + return ((unsigned long)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned subtraction with halved results. + \details This function enables you to perform four unsigned 8-bit integer subtractions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n + the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n + the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n + the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] - val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] - val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] - val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] - val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __UHSUB8(unsigned long x, unsigned long y) +{ + int32_t r, s, t, u; + + r = ((((x << 24) >> 24) - ((y << 24) >> 24)) >> 1) & 0x000000FF; + s = ((((x << 16) >> 24) - ((y << 16) >> 24)) >> 1) & 0x000000FF; + t = ((((x << 8) >> 24) - ((y << 8) >> 24)) >> 1) & 0x000000FF; + u = ((((x) >> 24) - ((y) >> 24)) >> 1) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Dual 16-bit add and subtract with exchange. + \details This function enables you to exchange the halfwords of the one operand, + then add the high halfwords and subtract the low halfwords, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the saturated subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the saturated addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __QASX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating addition and subtraction with exchange. + \details This function enables you to exchange the halfwords of the second operand and + perform one unsigned 16-bit integer addition and one unsigned 16-bit subtraction, + saturating the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the saturated subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the saturated addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __UQASX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit addition and subtraction with exchange. + \details It enables you to exchange the halfwords of the second operand, add the high halfwords + and subtract the low halfwords. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SASX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition and subtraction with exchange. + \details This function enables you to exchange the two halfwords of the second operand, + add the high halfwords and subtract the low halfwords. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __UASX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) - ((y) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed addition and subtraction with halved results. + \details This function enables you to exchange the two halfwords of one operand, perform one + signed 16-bit integer addition and one signed 16-bit subtraction, and halve the results. + \param [in] x first 16-bit operands. + \param [in] y second 16-bit operands. + \return the halved subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the halved addition of the low halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] + val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __SHASX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition and subtraction with halved results and exchange. + \details This function enables you to exchange the halfwords of the second operand, + add the high halfwords and subtract the low halfwords, halving the results. + \param [in] x first operand for the subtraction in the low halfword, and + the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, and + the second operand for the addition in the low halfword. + \return the halved subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the halved addition of the low halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] + val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __UHASX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit subtract and add with exchange. + \details This function enables you to exchange the halfwords of one operand, + then subtract the high halfwords and add the low halfwords, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the saturated addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the saturated subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __QSAX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating subtraction and addition with exchange. + \details This function enables you to exchange the halfwords of the second operand and perform + one unsigned 16-bit integer subtraction and one unsigned 16-bit addition, saturating + the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the saturated addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the saturated subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __UQSAX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit unsigned subtract and add with exchange. + \details This function enables you to exchange the halfwords of the second operand, + subtract the high halfwords and add the low halfwords. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __USAX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) + ((y) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction and addition with exchange. + \details This function enables you to exchange the two halfwords of one operand and perform one + 16-bit integer subtraction and one 16-bit addition. + \param [in] x first operand for the addition in the low halfword, and the first operand + for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, and the second + operand for the subtraction in the low halfword. + \return the addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SSAX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + + +/** + \brief Dual 16-bit signed subtraction and addition with halved results. + \details This function enables you to exchange the two halfwords of one operand, perform one signed + 16-bit integer subtraction and one signed 16-bit addition, and halve the results. + \param [in] x first 16-bit operands. + \param [in] y second 16-bit operands. + \return the halved addition of the low halfword in the first operand and the + high halfword in the second operand, in the low halfword of the return value.\n + the halved subtraction of the low halfword in the second operand from the + high halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] - val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __SHSAX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((unsigned long)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtraction and addition with halved results and exchange. + \details This function enables you to exchange the halfwords of the second operand, + subtract the high halfwords and add the low halfwords, halving the results. + \param [in] x first operand for the addition in the low halfword, and + the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, and + the second operand for the subtraction in the low halfword. + \return the halved addition of the low halfword in the first operand and the + high halfword in the second operand, in the low halfword of the return value.\n + the halved subtraction of the low halfword in the second operand from the + high halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] - val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE unsigned long __UHSAX(unsigned long x, unsigned long y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed multiply with exchange returning difference. + \details This function enables you to perform two 16-bit signed multiplications, subtracting + one of the products from the other. The halfwords of the second operand are exchanged + before performing the arithmetic. This produces top * bottom and bottom * top multiplication. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the difference of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 - p2 + */ +__ALWAYS_STATIC_INLINE unsigned long __SMUSDX(unsigned long x, unsigned long y) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)))); +} + +/** + \brief Sum of dual 16-bit signed multiply with exchange. + \details This function enables you to perform two 16-bit signed multiplications with exchanged + halfwords of the second operand, adding the products together. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the sum of the products of the two 16-bit signed multiplications with exchanged halfwords of the second operand. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 + p2 + */ +__ALWAYS_STATIC_INLINE unsigned long __SMUADX(unsigned long x, unsigned long y) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)))); +} + + +/** + \brief Saturating add. + \details This function enables you to obtain the saturating add of two integers. + \param [in] x first summand of the saturating add operation. + \param [in] y second summand of the saturating add operation. + \return the saturating addition of val1 and val2. + \remark + res[31:0] = SAT(val1 + SAT(val2)) + */ +__ALWAYS_STATIC_INLINE int32_t __QADD(int32_t x, int32_t y) +{ + int32_t result; + + if (y >= 0) { + if ((int32_t)((unsigned long)x + (unsigned long)y) >= x) { + result = x + y; + } else { + result = 0x7FFFFFFF; + } + } else { + if ((int32_t)((unsigned long)x + (unsigned long)y) < x) { + result = x + y; + } else { + result = 0x80000000; + } + } + + return result; +} + +/** + \brief Saturating subtract. + \details This function enables you to obtain the saturating add of two integers. + \param [in] x first summand of the saturating add operation. + \param [in] y second summand of the saturating add operation. + \return the saturating addition of val1 and val2. + \remark + res[31:0] = SAT(val1 - SAT(val2)) + */ +__ALWAYS_STATIC_INLINE int32_t __QSUB(int32_t x, int32_t y) +{ + int64_t tmp; + int32_t result; + + tmp = (int64_t)x - (int64_t)y; + + if (tmp > 0x7fffffff) { + tmp = 0x7fffffff; + } else if (tmp < (-2147483647 - 1)) { + tmp = -2147483647 - 1; + } + + result = tmp; + return result; +} + +/** + \brief Dual 16-bit signed multiply with single 32-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications, + adding both results to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value, as a 32-bit integer. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 + p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLAD(unsigned long x, unsigned long y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Pre-exchanged dual 16-bit signed multiply with single 32-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications with exchanged + halfwords of the second operand, adding both results to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication with exchanged halfwords of the second + operand added to the accumulate value, as a 32-bit integer. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 + p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLADX(unsigned long x, unsigned long y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate. + \details This function enables you to perform two 16-bit signed multiplications, take the + difference of the products, subtracting the high halfword product from the low + halfword product, and add the difference to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 - p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLSD(unsigned long x, unsigned long y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate. + \details This function enables you to exchange the halfwords in the second operand, then perform two 16-bit + signed multiplications. The difference of the products is added to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 - p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLSDX(unsigned long x, unsigned long y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with single 64-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications, adding both results + to a 64-bit accumulate operand. Overflow is only possible as a result of the 64-bit addition. + This overflow is not detected if it occurs. Instead, the result wraps around modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + sum = p1 + p2 + val3[63:32][31:0] \n + res[63:32] = sum[63:32] \n + res[31:0] = sum[31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLALD(unsigned long x, unsigned long y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange with single 64-bit accumulator. + \details This function enables you to exchange the halfwords of the second operand, and perform two + signed 16-bit multiplications, adding both results to a 64-bit accumulate operand. Overflow + is only possible as a result of the 64-bit addition. This overflow is not detected if it occurs. + Instead, the result wraps around modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + sum = p1 + p2 + val3[63:32][31:0] \n + res[63:32] = sum[63:32] \n + res[31:0] = sum[31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLALDX(unsigned long x, unsigned long y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief dual 16-bit signed multiply subtract with 64-bit accumulate. + \details This function It enables you to perform two 16-bit signed multiplications, take the difference + of the products, subtracting the high halfword product from the low halfword product, and add the + difference to a 64-bit accumulate operand. Overflow cannot occur during the multiplications or the + subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow is not + detected. Instead, the result wraps round to modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[63:32][31:0] = p1 - p2 + val3[63:32][31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLSLD(unsigned long x, unsigned long y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 64-bit accumulate. + \details This function enables you to exchange the halfwords of the second operand, perform two 16-bit multiplications, + adding the difference of the products to a 64-bit accumulate operand. Overflow cannot occur during the + multiplications or the subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow + is not detected. Instead, the result wraps round to modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[63:32][31:0] = p1 - p2 + val3[63:32][31:0] + */ +__ALWAYS_STATIC_INLINE uint64_t __SMLSLDX(unsigned long x, unsigned long y, uint64_t sum) +{ + return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((uint64_t)sum)))); +} + +/** + \brief 32-bit signed multiply with 32-bit truncated accumulator. + \details This function enables you to perform a signed 32-bit multiplications, adding the most + significant 32 bits of the 64-bit result to a 32-bit accumulate operand. + \param [in] x first operand for multiplication. + \param [in] y second operand for multiplication. + \param [in] sum accumulate value. + \return the product of multiplication (most significant 32 bits) is added to the accumulate value, as a 32-bit integer. + \remark + p = val1 * val2 \n + res[31:0] = p[63:32] + val3[31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMMLA(int32_t x, int32_t y, int32_t sum) +{ + return (unsigned long)((int32_t)((int64_t)((int64_t)x * (int64_t)y) >> 32) + sum); +} + +/** + \brief Sum of dual 16-bit signed multiply. + \details This function enables you to perform two 16-bit signed multiplications, adding the products together. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the sum of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 + p2 + */ +__ALWAYS_STATIC_INLINE unsigned long __SMUAD(unsigned long x, unsigned long y) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)))); +} + +/** + \brief Dual 16-bit signed multiply returning difference. + \details This function enables you to perform two 16-bit signed multiplications, taking the difference + of the products by subtracting the high halfword product from the low halfword product. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the difference of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 - p2 + */ +__ALWAYS_STATIC_INLINE unsigned long __SMUSD(unsigned long x, unsigned long y) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)))); +} + +/** + \brief Dual extracted 8-bit to 16-bit signed addition. + \details This function enables you to extract two 8-bit values from the second operand (at bit positions + [7:0] and [23:16]), sign-extend them to 16-bits each, and add the results to the first operand. + \param [in] x values added to the sign-extended to 16-bit values. + \param [in] y two 8-bit values to be extracted and sign-extended. + \return the addition of val1 and val2, where the 8-bit values in val2[7:0] and + val2[23:16] have been extracted and sign-extended prior to the addition. + \remark + res[15:0] = val1[15:0] + SignExtended(val2[7:0]) \n + res[31:16] = val1[31:16] + SignExtended(val2[23:16]) + */ +__ALWAYS_STATIC_INLINE unsigned long __SXTAB16(unsigned long x, unsigned long y) +{ + return ((unsigned long)((((((int32_t)y << 24) >> 24) + (((int32_t)x << 16) >> 16)) & (int32_t)0x0000FFFF) | + (((((int32_t)y << 8) >> 8) + (((int32_t)x >> 16) << 16)) & (int32_t)0xFFFF0000))); +} + +/** + \brief Extracted 16-bit to 32-bit unsigned addition. + \details This function enables you to extract two 8-bit values from one operand, zero-extend + them to 16 bits each, and add the results to two 16-bit values from another operand. + \param [in] x values added to the zero-extended to 16-bit values. + \param [in] y two 8-bit values to be extracted and zero-extended. + \return the addition of val1 and val2, where the 8-bit values in val2[7:0] and + val2[23:16] have been extracted and zero-extended prior to the addition. + \remark + res[15:0] = ZeroExt(val2[7:0] to 16 bits) + val1[15:0] \n + res[31:16] = ZeroExt(val2[31:16] to 16 bits) + val1[31:16] + */ +__ALWAYS_STATIC_INLINE unsigned long __UXTAB16(unsigned long x, unsigned long y) +{ + return ((unsigned long)(((((y << 24) >> 24) + ((x << 16) >> 16)) & 0x0000FFFF) | + ((((y << 8) >> 8) + ((x >> 16) << 16)) & 0xFFFF0000))); +} + +/** + \brief Dual extract 8-bits and sign extend each to 16-bits. + \details This function enables you to extract two 8-bit values from an operand and sign-extend them to 16 bits each. + \param [in] x two 8-bit values in val[7:0] and val[23:16] to be sign-extended. + \return the 8-bit values sign-extended to 16-bit values.\n + sign-extended value of val[7:0] in the low halfword of the return value.\n + sign-extended value of val[23:16] in the high halfword of the return value. + \remark + res[15:0] = SignExtended(val[7:0]) \n + res[31:16] = SignExtended(val[23:16]) + */ +__ALWAYS_STATIC_INLINE unsigned long __SXTB16(unsigned long x) +{ + return ((unsigned long)(((((int32_t)x << 24) >> 24) & (int32_t)0x0000FFFF) | + ((((int32_t)x << 8) >> 8) & (int32_t)0xFFFF0000))); +} + +/** + \brief Dual extract 8-bits and zero-extend to 16-bits. + \details This function enables you to extract two 8-bit values from an operand and zero-extend them to 16 bits each. + \param [in] x two 8-bit values in val[7:0] and val[23:16] to be zero-extended. + \return the 8-bit values sign-extended to 16-bit values.\n + sign-extended value of val[7:0] in the low halfword of the return value.\n + sign-extended value of val[23:16] in the high halfword of the return value. + \remark + res[15:0] = SignExtended(val[7:0]) \n + res[31:16] = SignExtended(val[23:16]) + */ +__ALWAYS_STATIC_INLINE unsigned long __UXTB16(unsigned long x) +{ + return ((unsigned long)((((x << 24) >> 24) & 0x0000FFFF) | + (((x << 8) >> 8) & 0xFFFF0000))); +} + +#endif /* _CSI_RV32_GCC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv64_gcc.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv64_gcc.h new file mode 100644 index 00000000000..f9872d772ba --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv64_gcc.h @@ -0,0 +1,4329 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + + +/****************************************************************************** + * @file csi_rv64_gcc.h + * @brief CSI Header File for GCC. + * @version V1.0 + * @date 01. Sep 2018 + ******************************************************************************/ + +#ifndef _CSI_RV64_GCC_H_ +#define _CSI_RV64_GCC_H_ + +#include + +#if CONFIG_CPU_XUANTIE_C907 || CONFIG_CPU_XUANTIE_C907FD || CONFIG_CPU_XUANTIE_C907FDV || CONFIG_CPU_XUANTIE_C907FDVM \ + || CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32 \ + || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \ + || CONFIG_CPU_XUANTIE_C910V2 || CONFIG_CPU_XUANTIE_C910V3 || CONFIG_CPU_XUANTIE_C910V3_CP \ + || CONFIG_CPU_XUANTIE_C920V2 || CONFIG_CPU_XUANTIE_C920V3 || CONFIG_CPU_XUANTIE_C920V3_CP \ + || CONFIG_CPU_XUANTIE_R908 || CONFIG_CPU_XUANTIE_R908FD || CONFIG_CPU_XUANTIE_R908FDV \ + || CONFIG_CPU_XUANTIE_R908_CP || CONFIG_CPU_XUANTIE_R908FD_CP || CONFIG_CPU_XUANTIE_R908FDV_CP +#define CBO_INSN_SUPPORT 1 +#endif + +#if CONFIG_INTC_CLIC_PLIC +#ifndef CONFIG_PLIC_IRQ_OFFSET +#define PLIC_IRQ_OFFSET 255U +#else +#define PLIC_IRQ_OFFSET CONFIG_PLIC_IRQ_OFFSET +#endif +#endif /* CONFIG_INTC_CLIC_PLIC */ + +/* ########################### Core Function Access ########################### */ +/** \ingroup CSI_Core_FunctionInterface + \defgroup CSI_Core_RegAccFunctions CSI Core Register Access Functions + @{ + */ +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by setting the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_irq(void) +{ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + __ASM volatile("csrs sstatus, 2"); + __ASM volatile("li a0, 0x222"); + __ASM volatile("csrs sie, a0"); +#else + __ASM volatile("csrs mstatus, 8"); + __ASM volatile("li a0, 0x888"); + __ASM volatile("csrs mie, a0"); +#endif +} + +/** + \brief Enable supervisor IRQ Interrupts + \details Enables IRQ interrupts by setting the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_supervisor_irq(void) +{ + __ASM volatile("csrs sstatus, 2"); + __ASM volatile("li a0, 0x222"); + __ASM volatile("csrs sie, a0"); +} + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by clearing the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_irq(void) +{ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + __ASM volatile("csrc sstatus, 2"); +#else + __ASM volatile("csrc mstatus, 8"); +#endif +} + +/** + \brief Disable supervisor IRQ Interrupts + \details Disables supervisor IRQ interrupts by clearing the IE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_supervisor_irq(void) +{ + __ASM volatile("csrc sstatus, 2"); +} + +/** + \brief Enable CoreTimer(within clint) Interrupts + */ +__ALWAYS_STATIC_INLINE void __enable_coret_irq(void) +{ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + __ASM volatile("li a0, 0x20"); + __ASM volatile("csrs sie, a0"); +#else + __ASM volatile("li a0, 0x80"); + __ASM volatile("csrs mie, a0"); +#endif +} + +/** + \brief Disable CoreTimer(within clint) Interrupts + */ +__ALWAYS_STATIC_INLINE void __disable_coret_irq(void) +{ +#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE + __ASM volatile("li a0, 0x20"); + __ASM volatile("csrc sie, a0"); +#else + __ASM volatile("li a0, 0x80"); + __ASM volatile("csrc mie, a0"); +#endif +} + +/** + \brief Get MXSTATUS + \details Returns the content of the MXSTATUS Register. + \return MXSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MXSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mxstatus" : "=r"(result)); + return (result); +} + +/** + \brief Set MXSTATUS + \details Writes the given value to the MXSTATUS Register. + \param [in] mxstatus MXSTATUS Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MXSTATUS(unsigned long mxstatus) +{ + __ASM volatile("csrw mxstatus, %0" : : "r"(mxstatus)); +} + +/** + \brief Get SXSTATUS + \details Returns the content of the SXSTATUS Register. + \return SXSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SXSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, sxstatus" : "=r"(result)); + return (result); +} + +#if __riscv_xlen == 32 +/** + \brief Get MENVCFGH + \details Returns the content of the MENVCFGH Register. + \return MENVCFGH Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MENVCFGH(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, menvcfgh" : "=r"(result)); + return (result); +} + +/** + \brief Set MENVCFGH + \details Writes the given value to the MENVCFGH Register. + \param [in] menvcfgh MENVCFGH Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MENVCFGH(unsigned long menvcfgh) +{ + __ASM volatile("csrw menvcfgh, %0" : : "r"(menvcfgh)); +} +#endif + +/** + \brief Get MENVCFG + \details Returns the content of the MENVCFG Register. + \return MENVCFG Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MENVCFG(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, menvcfg" : "=r"(result)); + return (result); +} + +/** + \brief Set MENVCFG + \details Writes the given value to the MENVCFG Register. + \param [in] menvcfg MENVCFG Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MENVCFG(unsigned long menvcfg) +{ + __ASM volatile("csrw menvcfg, %0" : : "r"(menvcfg)); +} + +/** + \brief Get CPU WORK MODE + \details Returns CPU WORK MODE. + \return CPU WORK MODE + */ +__ALWAYS_STATIC_INLINE unsigned long __get_CPU_WORK_MODE(void) +{ + unsigned long result; + __ASM volatile("csrr %0, sxstatus" : "=r"(result)); + return ((result >> 30U) & 0x3U); +} + +/** + \brief Set MEPC + \details Writes the given value to the MEPC Register. + \param [in] mepc MEPC Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MEPC(unsigned long mepc) +{ + __ASM volatile("csrw mepc, %0" : : "r"(mepc)); +} + +/** + \brief Get MEPC + \details Returns the content of the MEPC Register. + \return MEPC Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MEPC(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mepc" : "=r"(result)); + return (result); +} + +/** + \brief Set SEPC + \details Writes the given value to the SEPC Register. + \param [in] sepc SEPC Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_SEPC(unsigned long sepc) +{ + __ASM volatile("csrw sepc, %0" : : "r"(sepc)); +} + +/** + \brief Get SEPC + \details Returns the content of the SEPC Register. + \return SEPC Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SEPC(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, sepc" : "=r"(result)); + return (result); +} + + +/** + \brief Get MSTATUS + \details Returns the content of the MSTATUS Register. + \return MSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mstatus" : "=r"(result)); + return (result); +} + +/** + \brief Set MSTATUS + \details Writes the given value to the MSTATUS Register. + \param [in] mstatus MSTATUS Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSTATUS(unsigned long mstatus) +{ + __ASM volatile("csrw mstatus, %0" : : "r"(mstatus)); +} + +/** + \brief Get MCOR + \details Returns the content of the MCOR Register. + \return MCOR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCOR(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mcor" : "=r"(result)); + return (result); +} + +/** + \brief Set MCOR + \details Writes the given value to the MCOR Register. + \param [in] mstatus MCOR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCOR(unsigned long mcor) +{ + __ASM volatile("csrw mcor, %0" : : "r"(mcor)); +} + +/** + \brief Get MHCR + \details Returns the content of the MHCR Register. + \return MHCR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHCR(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mhcr" : "=r"(result)); + return (result); +} + +/** + \brief Set MHCR + \details Writes the given value to the MHCR Register. + \param [in] mstatus MHCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MHCR(unsigned long mhcr) +{ + __ASM volatile("csrw mhcr, %0" : : "r"(mhcr)); +} + +/** + \brief Get MHINT + \details Returns the content of the MHINT Register. + \return MHINT Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHINT(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mhint" : "=r"(result)); + return (result); +} + +/** + \brief Set MHINT + \details Writes the given value to the MHINT Register. + \param [in] mstatus MHINT Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MHINT(unsigned long mhint) +{ + __ASM volatile("csrw mhint, %0" : : "r"(mhint)); +} + +/** + \brief Get MCCR2 + \details Returns the content of the MCCR2 Register. + \return MCCR2 Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCCR2(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mccr2" : "=r"(result)); + return (result); +} + +/** + \brief Set MCCR2 + \details Writes the given value to the MCCR2 Register. + \param [in] mstatus MCCR2 Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCCR2(unsigned long mccr2) +{ + __ASM volatile("csrw mccr2, %0" : : "r"(mccr2)); +} + +/** + \brief Get MISA Register + \details Returns the content of the MISA Register. + \return MISA Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MISA(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, misa" : "=r"(result)); + return (result); +} + +/** + \brief Set MISA + \details Writes the given value to the MISA Register. + \param [in] misa MISA Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MISA(unsigned long misa) +{ + __ASM volatile("csrw misa, %0" : : "r"(misa)); +} + +/** + \brief Get MIE Register + \details Returns the content of the MIE Register. + \return MIE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIE(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mie" : "=r"(result)); + return (result); +} + +/** + \brief Set MIE + \details Writes the given value to the MIE Register. + \param [in] mie MIE Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MIE(unsigned long mie) +{ + __ASM volatile("csrw mie, %0" : : "r"(mie)); +} + +/** + \brief Get MTVEC Register + \details Returns the content of the MTVEC Register. + \return MTVEC Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTVEC(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mtvec" : "=r"(result)); + return (result); +} + +/** + \brief Set MTVEC + \details Writes the given value to the MTVEC Register. + \param [in] mtvec MTVEC Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MTVEC(unsigned long mtvec) +{ + __ASM volatile("csrw mtvec, %0" : : "r"(mtvec)); +} + +/** + \brief Set MTVT + \details Writes the given value to the MTVT Register. + \param [in] mtvt MTVT Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MTVT(unsigned long mtvt) +{ + __ASM volatile("csrw mtvt, %0" : : "r"(mtvt)); +} + +/** + \brief Get MTVT Register + \details Returns the content of the MTVT Register. + \return MTVT Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTVT(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mtvt" : "=r"(result)); + return (result); +} + +/** + \brief Get MTIME + \details Returns the content of the MTIME Register. + \return MTIME Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTIME(void) +{ + unsigned long result; + + __ASM volatile("rdtime %0" : "=r"(result)); + //__ASM volatile("csrr %0, 0xc01" : "=r"(result)); + return (result); +} + +/** + \brief Get SP + \details Returns the content of the SP Register. + \return SP Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SP(void) +{ + unsigned long result; + + __ASM volatile("mv %0, sp" : "=r"(result)); + return (result); +} + +/** + \brief Set SP + \details Writes the given value to the SP Register. + \param [in] sp SP Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_SP(unsigned long sp) +{ + __ASM volatile("mv sp, %0" : : "r"(sp): "sp"); +} + +/** + \brief Get MSCRATCH Register + \details Returns the content of the MSCRATCH Register. + \return MSCRATCH Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MSCRATCH(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mscratch" : "=r"(result)); + return (result); +} + +/** + \brief Set MSCRATCH + \details Writes the given value to the MSCRATCH Register. + \param [in] mscratch MSCRATCH Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSCRATCH(unsigned long mscratch) +{ + __ASM volatile("csrw mscratch, %0" : : "r"(mscratch)); +} + +/** + \brief Get MCAUSE Register + \details Returns the content of the MCAUSE Register. + \return MCAUSE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCAUSE(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mcause" : "=r"(result)); + return (result); +} + +/** + \brief Get SCAUSE Register + \details Returns the content of the SCAUSE Register. + \return SCAUSE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SCAUSE(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, scause" : "=r"(result)); + return (result); +} + +/** + \brief Get MNXTI Register + \details Returns the content of the MNXTI Register. + \return MNXTI Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MNXTI(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mnxti" : "=r"(result)); + return (result); +} + +/** + \brief Set MNXTI + \details Writes the given value to the MNXTI Register. + \param [in] mnxti MNXTI Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MNXTI(unsigned long mnxti) +{ + __ASM volatile("csrw mnxti, %0" : : "r"(mnxti)); +} + +/** + \brief Get MINTSTATUS Register + \details Returns the content of the MINTSTATUS Register. + \return MINTSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MINTSTATUS(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mintstatus" : "=r"(result)); + return (result); +} + +/** + \brief Get MTVAL Register + \details Returns the content of the MTVAL Register. + \return MTVAL Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTVAL(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mtval" : "=r"(result)); + return (result); +} + +/** + \brief Get MIP Register + \details Returns the content of the MIP Register. + \return MIP Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIP(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mip" : "=r"(result)); + return (result); +} + +/** + \brief Set MIP + \details Writes the given value to the MIP Register. + \param [in] mip MIP Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MIP(unsigned long mip) +{ + __ASM volatile("csrw mip, %0" : : "r"(mip)); +} + +/** + \brief Get MCYCLEL Register + \details Returns the content of the MCYCLEL Register. + \return MCYCLE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCYCLE(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mcycle" : "=r"(result)); + return (result); +} + +/** + \brief Set MCYCLE + \details Write MCYCLE Register + \param [in] value MCYCLE Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCYCLE(unsigned long value) +{ + __ASM volatile("csrw mcycle, %0" : : "r"(value)); +} + +/** + \brief Get MCYCLEH Register + \details Returns the content of the MCYCLEH Register. + \return MCYCLEH Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCYCLEH(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mcycleh" : "=r"(result)); + return (result); +} + +/** + \brief Set MCYCLEH + \details Write MCYCLEH Register + \param [in] value MCYCLEH Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCYCLEH(unsigned long value) +{ + __ASM volatile("csrw mcycleh, %0" : : "r"(value)); +} + +/** + \brief Get MINSTRET Register + \details Returns the content of the MINSTRET Register. + \return MINSTRET Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MINSTRET(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, minstret" : "=r"(result)); + return (result); +} + +/** + \brief Set MINSTRET + \details Write MINSTRET Register + \param [in] value MINSTRET Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MINSTRET(unsigned long value) +{ + __ASM volatile("csrw minstret, %0" : : "r"(value)); +} + +/** + \brief Get MINSTRETH Register + \details Returns the content of the MINSTRETH Register. + \return MINSTRETH Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MINSTRETH(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, minstreth" : "=r"(result)); + return (result); +} + +/** + \brief Set MINSTRETH + \details Write MINSTRETH Register + \param [in] value MINSTRETH Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MINSTRETH(unsigned long value) +{ + __ASM volatile("csrw minstreth, %0" : : "r"(value)); +} + +/** + \brief Get MVENDORID Register + \details Returns the content of the MVENDROID Register. + \return MVENDORID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MVENDORID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mvendorid" : "=r"(result)); + return (result); +} + +/** + \brief Get MARCHID Register + \details Returns the content of the MARCHID Register. + \return MARCHID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MARCHID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, marchid" : "=r"(result)); + return (result); +} + +/** + \brief Get MIMPID Register + \details Returns the content of the MIMPID Register. + \return MIMPID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIMPID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mimpid" : "=r"(result)); + return (result); +} + +/** + \brief Get MHARTID Register + \details Returns the content of the MHARTID Register. + \return MHARTID Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHARTID(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, mhartid" : "=r"(result)); + return (result); +} + +/** + \brief Get PMPCFGx Register + \details Returns the content of the PMPCFGx Register. + \return PMPCFGx Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG0(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg0" : "=r"(result)); + return (result); +} + +#if __riscv_xlen == 32 +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG1(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg1" : "=r"(result)); + return (result); +} +#endif + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG2(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg2" : "=r"(result)); + return (result); +} + +#if __riscv_xlen == 32 +__ALWAYS_STATIC_INLINE unsigned long __get_PMPCFG3(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpcfg3" : "=r"(result)); + return (result); +} +#endif + +/** + \brief Get PMPxCFG Register by index + \details Returns the content of the PMPxCFG Register. + \param [in] idx PMP region index + \return PMPxCFG Register value + */ +__STATIC_INLINE uint8_t __get_PMPxCFG(unsigned long idx) +{ + unsigned long pmpcfgx = 0; + +#if __riscv_xlen == 32 + if (idx < 4) { + pmpcfgx = __get_PMPCFG0(); + } else if (idx >= 4 && idx < 8) { + idx -= 4; + pmpcfgx = __get_PMPCFG1(); + } else if (idx >= 8 && idx < 12) { + idx -= 8; + pmpcfgx = __get_PMPCFG2(); + } else if (idx >= 12 && idx < 16) { + idx -= 12; + pmpcfgx = __get_PMPCFG3(); + } else { + return 0; + } +#else + if (idx < 8) { + pmpcfgx = __get_PMPCFG0(); + } else if (idx >= 8 && idx < 16) { + idx -= 8; + pmpcfgx = __get_PMPCFG2(); + } else { + return 0; + } +#endif + + return (uint8_t)((pmpcfgx & (0xFF << (idx << 3))) >> (idx << 3)); +} + +/** + \brief Set PMPCFGx + \details Writes the given value to the PMPCFGx Register. + \param [in] pmpcfg PMPCFGx Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_PMPCFG0(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg0, %0" : : "r"(pmpcfg)); +} + +#if __riscv_xlen == 32 +__ALWAYS_STATIC_INLINE void __set_PMPCFG1(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg1, %0" : : "r"(pmpcfg)); +} +#endif + +__ALWAYS_STATIC_INLINE void __set_PMPCFG2(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg2, %0" : : "r"(pmpcfg)); +} + +#if __riscv_xlen == 32 +__ALWAYS_STATIC_INLINE void __set_PMPCFG3(unsigned long pmpcfg) +{ + __ASM volatile("csrw pmpcfg3, %0" : : "r"(pmpcfg)); +} +#endif + +/** + \brief Set PMPxCFG by index + \details Writes the given value to the PMPxCFG Register. + \param [in] idx PMPx region index + \param [in] pmpxcfg PMPxCFG Register value to set + */ +__STATIC_INLINE void __set_PMPxCFG(unsigned long idx, uint8_t pmpxcfg) +{ + unsigned long pmpcfgx = 0; + +#if __riscv_xlen == 32 + if (idx < 4) { + pmpcfgx = __get_PMPCFG0(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | ((unsigned long)(pmpxcfg) << (idx << 3)); + __set_PMPCFG0(pmpcfgx); + } else if (idx >= 4 && idx < 8) { + idx -= 4; + pmpcfgx = __get_PMPCFG1(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | ((unsigned long)(pmpxcfg) << (idx << 3)); + __set_PMPCFG1(pmpcfgx); + } else if (idx >= 8 && idx < 12) { + idx -= 8; + pmpcfgx = __get_PMPCFG2(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | ((unsigned long)(pmpxcfg) << (idx << 3)); + __set_PMPCFG2(pmpcfgx); + } else if (idx >= 12 && idx < 16) { + idx -= 12; + pmpcfgx = __get_PMPCFG3(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | ((unsigned long)(pmpxcfg) << (idx << 3)); + __set_PMPCFG3(pmpcfgx); + } else { + return; + } +#else + if (idx < 8) { + pmpcfgx = __get_PMPCFG0(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | ((unsigned long)(pmpxcfg) << (idx << 3)); + __set_PMPCFG0(pmpcfgx); + } else if (idx >= 8 && idx < 16) { + idx -= 8; + pmpcfgx = __get_PMPCFG2(); + pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | ((unsigned long)(pmpxcfg) << (idx << 3)); + __set_PMPCFG2(pmpcfgx); + } else { + return; + } +#endif +} + +/** + \brief Get PMPADDRx Register + \details Returns the content of the PMPADDRx Register. + \return PMPADDRx Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR0(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr0" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR1(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr1" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR2(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr2" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR3(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr3" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR4(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr4" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR5(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr5" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR6(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr6" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR7(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr7" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR8(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr8" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR9(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr9" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR10(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr10" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR11(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr11" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR12(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr12" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR13(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr13" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR14(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr14" : "=r"(result)); + return (result); +} + +__ALWAYS_STATIC_INLINE unsigned long __get_PMPADDR15(void) +{ + unsigned long result; + + __ASM volatile("csrr %0, pmpaddr15" : "=r"(result)); + return (result); +} + +/** + \brief Get PMPADDRx Register by index + \details Returns the content of the PMPADDRx Register. + \param [in] idx PMP region index + \return PMPADDRx Register value + */ +__STATIC_INLINE unsigned long __get_PMPADDRx(unsigned long idx) +{ + switch (idx) { + case 0: + return __get_PMPADDR0(); + + case 1: + return __get_PMPADDR1(); + + case 2: + return __get_PMPADDR2(); + + case 3: + return __get_PMPADDR3(); + + case 4: + return __get_PMPADDR4(); + + case 5: + return __get_PMPADDR5(); + + case 6: + return __get_PMPADDR6(); + + case 7: + return __get_PMPADDR7(); + + case 8: + return __get_PMPADDR8(); + + case 9: + return __get_PMPADDR9(); + + case 10: + return __get_PMPADDR10(); + + case 11: + return __get_PMPADDR11(); + + case 12: + return __get_PMPADDR12(); + + case 13: + return __get_PMPADDR13(); + + case 14: + return __get_PMPADDR14(); + + case 15: + return __get_PMPADDR15(); + + default: + return 0; + } +} + +/** + \brief Set PMPADDRx + \details Writes the given value to the PMPADDRx Register. + \param [in] pmpaddr PMPADDRx Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_PMPADDR0(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr0, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR1(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr1, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR2(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr2, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR3(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr3, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR4(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr4, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR5(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr5, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR6(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr6, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR7(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr7, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR8(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr8, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR9(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr9, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR10(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr10, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR11(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr11, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR12(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr12, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR13(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr13, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR14(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr14, %0" : : "r"(pmpaddr)); +} + +__ALWAYS_STATIC_INLINE void __set_PMPADDR15(unsigned long pmpaddr) +{ + __ASM volatile("csrw pmpaddr15, %0" : : "r"(pmpaddr)); +} + +/** + \brief Set PMPADDRx by index + \details Writes the given value to the PMPADDRx Register. + \param [in] idx PMP region index + \param [in] pmpaddr PMPADDRx Register value to set + */ +__STATIC_INLINE void __set_PMPADDRx(unsigned long idx, unsigned long pmpaddr) +{ + switch (idx) { + case 0: + __set_PMPADDR0(pmpaddr); + break; + + case 1: + __set_PMPADDR1(pmpaddr); + break; + + case 2: + __set_PMPADDR2(pmpaddr); + break; + + case 3: + __set_PMPADDR3(pmpaddr); + break; + + case 4: + __set_PMPADDR4(pmpaddr); + break; + + case 5: + __set_PMPADDR5(pmpaddr); + break; + + case 6: + __set_PMPADDR6(pmpaddr); + break; + + case 7: + __set_PMPADDR7(pmpaddr); + break; + + case 8: + __set_PMPADDR8(pmpaddr); + break; + + case 9: + __set_PMPADDR9(pmpaddr); + break; + + case 10: + __set_PMPADDR10(pmpaddr); + break; + + case 11: + __set_PMPADDR11(pmpaddr); + break; + + case 12: + __set_PMPADDR12(pmpaddr); + break; + + case 13: + __set_PMPADDR13(pmpaddr); + break; + + case 14: + __set_PMPADDR14(pmpaddr); + break; + + case 15: + __set_PMPADDR15(pmpaddr); + break; + + default: + return; + } +} + +/** + \brief Get MCOUNTEREN + \details Returns the content of the MCOUNTEREN Register. + \return MCOUNTEREN Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCOUNTEREN(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mcounteren" : "=r"(result)); + return (result); +} + +/** + \brief Set MCOUNTEREN + \details Writes the given value to the MCOUNTEREN Register. + \param [in] mcounteren MCOUNTEREN Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCOUNTEREN(uint32_t mcounteren) +{ + __ASM volatile("csrw mcounteren, %0" : : "r"(mcounteren)); +} + +/** + \brief Get MCOUNTERWEN + \details Returns the content of the MCOUNTERWEN Register. + \return MCOUNTERWEN Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCOUNTERWEN(void) +{ + uint32_t result; + + __ASM volatile("csrr %0, mcounterwen" : "=r"(result)); + return (result); +} + +/** + \brief Set MCOUNTERWEN + \details Writes the given value to the MCOUNTERWEN Register. + \param [in] mcounterwen MCOUNTERWEN Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCOUNTERWEN(uint32_t mcounterwen) +{ + __ASM volatile("csrw mcounterwen, %0" : : "r"(mcounterwen)); +} +/** + \brief Set MEDELEG Register + \details Writes the given value to the MEDELEG Register. + */ +__ALWAYS_STATIC_INLINE void __set_MEDELEG(unsigned long x) +{ + __ASM volatile("csrw medeleg, %0"::"r"(x)); +} + +/** + \brief Set MEDELEG Register + \details Writes the given value to the MEDELEG Register. + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MEDELEG(void) +{ + unsigned long x; + __ASM volatile("csrr %0, medeleg":"=r"(x)); + return x; +} + +/** + \brief Set MIDELEG Register + \details Writes the given value to the MIDELEG Register. + */ +__ALWAYS_STATIC_INLINE void __set_MIDELEG(unsigned long x) +{ + __ASM volatile("csrw mideleg, %0"::"r"(x)); +} + +/** + \brief Get MIDELEG Register + \details Returns the content of the MIDELEG Register. + \return MIDELEG Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIDELEG(void) +{ + unsigned long x; + __ASM volatile("csrr %0, mideleg":"=r"(x)); + return x; +} + +/** + \brief Set SSTATUS Register + \details Writes the given value to the SSTATUS Register. + */ +__ALWAYS_STATIC_INLINE void __set_SSTATUS(unsigned long x) +{ + __ASM volatile("csrw sstatus, %0"::"r"(x)); +} + +/** + \brief Get SSTATUS Register + \details Returns the content of the SSTATUS Register. + \return SSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SSTATUS(void) +{ + unsigned long x; + __ASM volatile("csrr %0, sstatus":"=r"(x)); + return x; +} + +/** + \brief Set SXSTATUS Register + \details Writes the given value to the SXSTATUS Register. + */ +__ALWAYS_STATIC_INLINE void __set_SXSTATUS(unsigned long x) +{ + __ASM volatile("csrw sxstatus, %0"::"r"(x)); +} + +/** + \brief Get SXSTATUS Register + \details Returns the content of the SXSTATUS Register. + \return SXSTATUS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get__SXSTATUS(void) +{ + unsigned long x; + __ASM volatile("csrr %0, sxstatus":"=r"(x)); + return x; +} + +/** + \brief Set SIE Register + \details Writes the given value to the SIE Register. + */ +__ALWAYS_STATIC_INLINE void __set_SIE(unsigned long x) +{ + __ASM volatile("csrw sie, %0"::"r"(x)); +} + +/** + \brief Get SIE Register + \details Returns the content of the SIE Register. + \return SIE Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SIE(void) +{ + unsigned long x; + __ASM volatile("csrr %0, sie":"=r"(x)); + return x; +} + +/** + \brief Set STVAC Register + \details Writes the given value to the STVEC Register. + */ +__ALWAYS_STATIC_INLINE void __set_STVEC(unsigned long x) +{ + __ASM volatile("csrw stvec, %0"::"r"(x)); +} + +/** + \brief Get STVAC Register + \details Returns the content of the STVAC Register. + \return STVAC Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_STVEC(void) +{ + unsigned long x; + __ASM volatile("csrr %0, stvec":"=r"(x)); + return x; +} + +/** + \brief Enable interrupts and exceptions + \details Enables interrupts and exceptions by setting the IE-bit and EE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __enable_excp_irq(void) +{ +#ifdef CONFIG_MMU + __enable_supervisor_irq(); +#else + __enable_irq(); +#endif +} + + +/** + \brief Disable interrupts and exceptions + \details Disables interrupts and exceptions by clearing the IE-bit and EE-bit in the PSR. + Can only be executed in Privileged modes. + */ +__ALWAYS_STATIC_INLINE void __disable_excp_irq(void) +{ +#ifdef CONFIG_MMU + __disable_supervisor_irq(); +#else + __disable_irq(); +#endif +} + +#define __CSI_GCC_OUT_REG(r) "=r" (r) +#define __CSI_GCC_USE_REG(r) "r" (r) + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__ALWAYS_STATIC_INLINE void __NOP(void) +{ + __ASM volatile("nop"); +} + +/** + \brief return from S-MODE + \details return from S-MODE. + */ +__ALWAYS_STATIC_INLINE void __SRET(void) +{ + __ASM volatile("sret"); +} + +/** + \brief return from M-MODE + \details return from M-MODE. + */ +__ALWAYS_STATIC_INLINE void __MRET(void) +{ + __ASM volatile("mret"); +} + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__ALWAYS_STATIC_INLINE void __WFI(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __WAIT(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Doze For Interrupt + \details Doze For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __DOZE(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Stop For Interrupt + \details Stop For Interrupt is a hint instruction that suspends execution until one interrupt occurs. + */ +__ALWAYS_STATIC_INLINE void __STOP(void) +{ + __ASM volatile("wfi"); +} + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__ALWAYS_STATIC_INLINE void __ISB(void) +{ + __ASM volatile("fence.i"); + __ASM volatile("fence r, r"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__ALWAYS_STATIC_INLINE void __DSB(void) +{ + __ASM volatile("fence iorw, iorw"); + __ASM volatile("sync"); +} + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__ALWAYS_STATIC_INLINE void __DMB(void) +{ + __ASM volatile("fence rw, rw"); +} + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__ALWAYS_STATIC_INLINE void __SYNC_IS(void) +{ + __ASM volatile("sync.is"); +} + +/** + \brief Invalid all icache + \details invalid all icache. + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IALL(void) +{ + __ASM volatile("icache.iall"); +} + +/** + \brief Invalid all icache and broadcast to other cores + \details Invalid all icache and broadcast to other cores + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IALLS(void) +{ + __ASM volatile("icache.ialls"); +} + +/** + \brief Invalid Icache by physical addr + \details Invalid Icache by physical addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IPA(unsigned long addr) +{ + __ASM volatile("icache.ipa %0" : : "r"(addr)); +} + +/** + \brief Invalid Icache by virsual addr + \details Invalid Icache by virsual addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IVA(unsigned long addr) +{ + __ASM volatile("icache.iva %0" : : "r"(addr)); +} + +/** + \brief Invalid all L1dcache + \details invalid all L1dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IALL(void) +{ + __ASM volatile("dcache.iall"); +} + +/** + \brief Clear all dcache + \details clear all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CALL(void) +{ + __ASM volatile("dcache.call"); +} + +/** + \brief Clear & invalid all dcache + \details clear & invalid all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIALL(void) +{ + __ASM volatile("dcache.ciall"); +} + +/** + \brief Clear & Invalid Dcache by way/set + \details Clear & Invalid Dcache by way/set + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CISW(unsigned long wayset) +{ + __ASM volatile("dcache.cisw %0" : : "r"(wayset)); +} + +#if CBO_INSN_SUPPORT +/** + \brief Clear Dcache/L2cache by addr + \details Clear Dcache/L2cache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __CBO_CLEAN(unsigned long addr) +{ + __ASM volatile("cbo.clean 0(%0)" : : "r"(addr)); +} + +/** + \brief Clear & Invalid Dcache/L2cache by addr + \details Clear & Invalid Dcache/L2cache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __CBO_FLUSH(unsigned long addr) +{ + __ASM volatile("cbo.flush 0(%0)" : : "r"(addr)); +} + +/** + \brief Invalid Dcache/L2cache by addr + \details Invalid Dcache/L2cache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __CBO_INVAL(unsigned long addr) +{ + __ASM volatile("cbo.inval 0(%0)" : : "r"(addr)); +} + +/** + \brief Set Dcache to zero by addr + \details Set Dcache to zero by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __CBO_ZERO(unsigned long addr) +{ + __ASM volatile("cbo.zero %0" : : "r"(addr)); +} +#else +/** + \brief Clear Dcache/L2cache by physical addr + \details Clear Dcache/L2cache by physical addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CPA(unsigned long addr) +{ + __ASM volatile("dcache.cpa %0" : : "r"(addr)); +} + +/** + \brief Clear Dcache/L2cache by virsual addr + \details Clear Dcache/L2cache by virsual addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CVA(unsigned long addr) +{ + __ASM volatile("dcache.cva %0" : : "r"(addr)); +} + +/** + \brief Clear & Invalid Dcache by physical addr + \details Clear & Invalid Dcache by physical addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIPA(unsigned long addr) +{ + __ASM volatile("dcache.cipa %0" : : "r"(addr)); +} + +/** + \brief Clear & Invalid Dcache by virsual addr + \details Clear & Invalid Dcache by virsual addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIVA(unsigned long addr) +{ + __ASM volatile("dcache.civa %0" : : "r"(addr)); +} + +/** + \brief Invalid Dcache/L2cache by physical addr + \details Invalid Dcache/L2cache by physical addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IPA(unsigned long addr) +{ + __ASM volatile("dcache.ipa %0" : : "r"(addr)); +} + +/** + \brief Invalid Dcache/L2cache by virsual addr + \details Invalid Dcache/L2cache by virsual addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IVA(unsigned long addr) +{ + __ASM volatile("dcache.iva %0" : : "r"(addr)); +} + +#endif + +/** + \brief Clear L1-Dcache by physical addr and broadcast to other cores + \details Clear L1-Dcache by physical addr and broadcast to other cores + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CPAL1(unsigned long addr) +{ + __ASM volatile("dcache.cpal1 %0" : : "r"(addr)); +} + +/** + \brief Clear L1-Dcache by virsual addr and broadcast to other cores + \details Clear L1-Dcache by virsual addr and broadcast to other cores + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CVAL1(unsigned long addr) +{ + __ASM volatile("dcache.cval1 %0" : : "r"(addr)); +} + +/** + \brief Invalid Dcache by way/set + \details Invalid Dcache by way/set + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_ISW(unsigned long wayset) +{ + __ASM volatile("dcache.isw %0" : : "r"(wayset)); +} + +#if (__L2CACHE_PRESENT == 1U) +/** + \brief Invalid L2 cache + \details invalid L2 cache. + */ +__ALWAYS_STATIC_INLINE void __L2CACHE_IALL(void) +{ + __ASM volatile("l2cache.iall"); +} + +/** + \brief Clear L2cache + \details clear L2cache. + */ +__ALWAYS_STATIC_INLINE void __L2CACHE_CALL(void) +{ + __ASM volatile("l2cache.call"); +} + +/** + \brief Clear&invalid L2cache + \details clear & invalid L2cache. + */ +__ALWAYS_STATIC_INLINE void __L2CACHE_CIALL(void) +{ + __ASM volatile("l2cache.ciall"); +} +#endif + +/** + \brief Get SATP + \details Returns the current value of the SATP. + \return SATP Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SATP(void) +{ + register unsigned long result; + + __ASM volatile("csrr %0, satp" : "=r"(result)); + return (result); +} + +/** + \brief Set SATP + \details Assigns the given value to the SATP. + \param [in] satp SATP value to set + */ +__ALWAYS_STATIC_INLINE void __set_SATP(unsigned long satp) +{ + __ASM volatile("sfence.vma"); + __ASM volatile("csrw satp, %0" : : "r"(satp)); +} + +/** + \brief Get SCER2 + \details Returns the current value of the SCER2. + \return SCER2 Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SCER2(void) +{ + register unsigned long result; + __ASM volatile("csrr %0, scer2" : "=r"(result)); + return (result); +} + +/** + \brief Set SCER2 + \details Assigns the given value to the SCER2. + \param [in] scer2 SCER2 value to set + */ +__ALWAYS_STATIC_INLINE void __set_SCER2(unsigned long scer2) +{ + __ASM volatile("csrw scer2, %0" : : "r"(scer2)); +} + +/** + \brief Get MCER2 + \details Returns the current value of the MCER2. + \return MCER2 Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCER2(void) +{ + register unsigned long result; + __ASM volatile("csrr %0, mcer2" : "=r"(result)); + return (result); +} + +/** + \brief Set MCER2 + \details Assigns the given value to the MCER2. + \param [in] mcer2 MCER2 value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCER2(unsigned long mcer2) +{ + __ASM volatile("csrw mcer2, %0" : : "r"(mcer2)); +} + +#if __riscv_xlen == 32 +/** + \brief Get MCER2H + \details Returns the current value of the MCER2H. + \return MCER2H Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCER2H(void) +{ + register unsigned long result; + __ASM volatile("csrr %0, mcer2h" : "=r"(result)); + return (result); +} + +/** + \brief Set MCER2H + \details Assigns the given value to the MCER2H. + \param [in] mcer2h MCER2H value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCER2H(unsigned long mcer2h) +{ + __ASM volatile("csrw mcer2h, %0" : : "r"(mcer2h)); +} +#endif + +/** + \brief Get SSBEPA2 + \details Returns the current value of the SSBEPA2. + \return SSBEPA2 Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SSBEPA2(void) +{ + register unsigned long result; + //__ASM volatile("csrr %0, ssbepa2" : "=r"(result)); + __ASM volatile("csrr %0, 0x5d2" : "=r"(result)); + return (result); +} + +/** + \brief Set SSBEPA2 + \details Assigns the given value to the SSBEPA2. + \param [in] ssbepa2 SSBEPA2 value to set + */ +__ALWAYS_STATIC_INLINE void __set_SSBEPA2(unsigned long ssbepa2) +{ + //__ASM volatile("csrw ssbepa2, %0" : : "r"(ssbepa2)); + __ASM volatile("csrw 0x5d2, %0" : : "r"(ssbepa2)); +} + +/** + \brief Get MSBEPA2 + \details Returns the current value of the MSBEPA2. + \return MSBEPA2 Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MSBEPA2(void) +{ + register unsigned long result; + //__ASM volatile("csrr %0, msbepa2" : "=r"(result)); + __ASM volatile("csrr %0, 0x7fc" : "=r"(result)); + return (result); +} + +/** + \brief Set MSBEPA2 + \details Assigns the given value to the MSBEPA2. + \param [in] msbepa2 MSBEPA2 value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSBEPA2(unsigned long msbepa2) +{ + //__ASM volatile("csrw msbepa2, %0" : : "r"(msbepa2)); + __ASM volatile("csrw 0x7fc, %0" : : "r"(msbepa2)); +} + +/** + \brief Get SCER + \details Returns the current value of the SCER. + \return SCER Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SCER(void) +{ + register unsigned long result; + __ASM volatile("csrr %0, scer" : "=r"(result)); + return (result); +} + +/** + \brief Set SCER + \details Assigns the given value to the SCER. + \param [in] scer SCER value to set + */ +__ALWAYS_STATIC_INLINE void __set_SCER(unsigned long scer) +{ + __ASM volatile("csrw scer, %0" : : "r"(scer)); +} + +/** + \brief Get MCER + \details Returns the current value of the MCER. + \return MCER Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCER(void) +{ + register unsigned long result; + __ASM volatile("csrr %0, mcer" : "=r"(result)); + return (result); +} + +/** + \brief Set MCER + \details Assigns the given value to the MCER. + \param [in] mcer MCER value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCER(unsigned long mcer) +{ + __ASM volatile("csrw mcer, %0" : : "r"(mcer)); +} + +#if __riscv_xlen == 32 +/** + \brief Get MCERH + \details Returns the current value of the MCERH. + \return MCERH Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MCERH(void) +{ + register unsigned long result; + __ASM volatile("csrr %0, mcerh" : "=r"(result)); + return (result); +} + +/** + \brief Set MCERH + \details Assigns the given value to the MCERH. + \param [in] mcerh MCERH value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCERH(unsigned long mcerh) +{ + __ASM volatile("csrw mcerh, %0" : : "r"(mcerh)); +} +#endif + +/** + \brief Get SSBEPA + \details Returns the current value of the SSBEPA. + \return SSBEPA Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_SSBEPA(void) +{ + register unsigned long result; + //__ASM volatile("csrr %0, ssbepa" : "=r"(result)); + __ASM volatile("csrr %0, 0x5d1" : "=r"(result)); + return (result); +} + +/** + \brief Set SSBEPA + \details Assigns the given value to the SSBEPA. + \param [in] ssbepa SSBEPA value to set + */ +__ALWAYS_STATIC_INLINE void __set_SSBEPA(unsigned long ssbepa) +{ + //__ASM volatile("csrw ssbepa, %0" : : "r"(ssbepa)); + __ASM volatile("csrw 0x5d1, %0" : : "r"(ssbepa)); +} + +/** + \brief Get MSBEPA + \details Returns the current value of the MSBEPA. + \return MSBEPA Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MSBEPA(void) +{ + register unsigned long result; + //__ASM volatile("csrr %0, msbepa" : "=r"(result)); + __ASM volatile("csrr %0, 0x7fb" : "=r"(result)); + return (result); +} + +/** + \brief Set MSBEPA + \details Assigns the given value to the MSBEPA. + \param [in] msbepa MSBEPA value to set + */ +__ALWAYS_STATIC_INLINE void __set_MSBEPA(unsigned long msbepa) +{ + //__ASM volatile("csrw msbepa, %0" : : "r"(msbepa)); + __ASM volatile("csrw 0x7fb, %0" : : "r"(msbepa)); +} + +/** + \brief Get ERRSTS + \details Returns the current value of the ERRSTS. + \return ERRSTS Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MIESR(void) +{ + register unsigned long result; + + __ASM volatile("csrr %0, miesr" : "=r"(result)); + return (result); +} + +/** + \brief Get MEICR2 + \details Returns the current value of the MEICR2. + \return MEICR2 Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MEICR2(void) +{ + register unsigned long result; + + __ASM volatile("csrr %0, meicr2" : "=r"(result)); + return (result); +} + +/** + \brief Set MEICR2 + \details Assigns the given value to the MEICR2. + \param [in] errinjcr MEICR2 value to set + */ +__ALWAYS_STATIC_INLINE void __set_MEICR2(unsigned long meicr2) +{ + __ASM volatile("csrw meicr2, %0" : : "r"(meicr2)); +} + +/** + \brief Get MEICR + \details Returns the current value of the MEICR. + \return MEICR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MEICR(void) +{ + register unsigned long result; + + __ASM volatile("csrr %0, meicr" : "=r"(result)); + return (result); +} + +/** + \brief Set MEICR + \details Assigns the given value to the MEICR. + \param [in] errinjcr MEICR value to set + */ +__ALWAYS_STATIC_INLINE void __set_MEICR(unsigned long meicr) +{ + __ASM volatile("csrw meicr, %0" : : "r"(meicr)); +} + +/** + \brief Get ITCMCR + \details Returns the content of the ITCMCR Register. + \return ITCMCR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MITCMCR(void) +{ + unsigned long result; + __ASM volatile("csrr %0, mitcmcr" : "=r"(result)); + return (result); +} + +/** + \brief Set ITCMCR + \details Writes the given value to the ITCMCR Register. + \param [in] itcmcr ITCMCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MITCMCR(unsigned long itcmcr) +{ + __ASM volatile("csrw mitcmcr, %0" : : "r"(itcmcr)); +} + +/** + \brief Get DTCMCR + \details Returns the content of the DTCMCR Register. + \return DTCMCR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MDTCMCR(void) +{ + unsigned long result; + __ASM volatile("csrr %0, mdtcmcr" : "=r"(result)); + return (result); +} + +/** + \brief Set DTCMCR + \details Writes the given value to the DTCMCR Register. + \param [in] dtcmcr DTCMCR Registed value to set + */ +__ALWAYS_STATIC_INLINE void __set_MDTCMCR(unsigned long dtcmcr) +{ + __ASM volatile("csrw mdtcmcr, %0" : : "r"(dtcmcr)); +} + +/** + \brief Get MFPPCR + \details Read MFPPCR Register. + \return MFPPCR Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MFPPCR(void) +{ + unsigned long result; + __ASM volatile("csrr %0, mfppcr" : "=r"(result)); + return (result); +} + +/** + \brief Set MFPPCR + \details Write MFPPCR Register. + \param [in] fppcr MFPPCR Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MFPPCR(unsigned long fppcr) +{ + __ASM volatile("csrw mfppcr, %0" : : "r"(fppcr)); +} + +/** + \brief Set MCOUNTINHIBIT + \details Write MCOUNTINHIBIT Register. + \param [in] value MCOUNTINHIBIT Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MCOUNTINHIBIT(uint32_t value) +{ + __ASM volatile("csrw mcountinhibit, %0" : : "r"(value)); +} + +/** + \brief Get MCOUNTINHIBIT + \details Read MCOUNTINHIBIT Register + \return MCOUNTINHIBIT Register value + */ +__ALWAYS_STATIC_INLINE unsigned int __get_MCOUNTINHIBIT(void) +{ + uint32_t result; + __ASM volatile("csrr %0, mcountinhibit" : "=r"(result)); + return result; +} + +/** + \brief Set MHPMEVENT + \details Write MHPMEVENT Register + \param [in] idx Index of MHPMEVENT Register + \param [in] value MHPMEVENT Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MHPMEVENT(unsigned long idx, unsigned long value) +{ + switch (idx) { + case 0: rv_csr_write(0x7E0, value); break; + case 2: rv_csr_write(0x7E1, value); break; + case 3: rv_csr_write(0x323, value); break; + case 4: rv_csr_write(0x324, value); break; + case 5: rv_csr_write(0x325, value); break; + case 6: rv_csr_write(0x326, value); break; + case 7: rv_csr_write(0x327, value); break; + case 8: rv_csr_write(0x328, value); break; + case 9: rv_csr_write(0x329, value); break; + case 10: rv_csr_write(0x32a, value); break; + case 11: rv_csr_write(0x32b, value); break; + case 12: rv_csr_write(0x32c, value); break; + case 13: rv_csr_write(0x32d, value); break; + case 14: rv_csr_write(0x32e, value); break; + case 15: rv_csr_write(0x32f, value); break; + case 16: rv_csr_write(0x330, value); break; + case 17: rv_csr_write(0x331, value); break; + case 18: rv_csr_write(0x332, value); break; + case 19: rv_csr_write(0x333, value); break; + case 20: rv_csr_write(0x334, value); break; + case 21: rv_csr_write(0x335, value); break; + case 22: rv_csr_write(0x336, value); break; + case 23: rv_csr_write(0x337, value); break; + case 24: rv_csr_write(0x338, value); break; + case 25: rv_csr_write(0x339, value); break; + case 26: rv_csr_write(0x33a, value); break; + case 27: rv_csr_write(0x33b, value); break; + case 28: rv_csr_write(0x33c, value); break; + case 29: rv_csr_write(0x33d, value); break; + case 30: rv_csr_write(0x33e, value); break; + case 31: rv_csr_write(0x33F, value); break; + default: break; + } +} + +/** + \brief Get MHPMEVENT + \details Read MHPMEVENT Register. + \param [in] idx Index of MHPMEVENT Register to read. + \return MHPMEVENT Register Value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHPMEVENT(unsigned long idx) +{ + switch (idx) { + case 0: return rv_csr_read(0x7E0); + case 2: return rv_csr_read(0x7E1); + case 3: return rv_csr_read(0x323); + case 4: return rv_csr_read(0x324); + case 5: return rv_csr_read(0x325); + case 6: return rv_csr_read(0x326); + case 7: return rv_csr_read(0x327); + case 8: return rv_csr_read(0x328); + case 9: return rv_csr_read(0x329); + case 10: return rv_csr_read(0x32a); + case 11: return rv_csr_read(0x32b); + case 12: return rv_csr_read(0x32c); + case 13: return rv_csr_read(0x32d); + case 14: return rv_csr_read(0x32e); + case 15: return rv_csr_read(0x32f); + case 16: return rv_csr_read(0x330); + case 17: return rv_csr_read(0x331); + case 18: return rv_csr_read(0x332); + case 19: return rv_csr_read(0x333); + case 20: return rv_csr_read(0x334); + case 21: return rv_csr_read(0x335); + case 22: return rv_csr_read(0x336); + case 23: return rv_csr_read(0x337); + case 24: return rv_csr_read(0x338); + case 25: return rv_csr_read(0x339); + case 26: return rv_csr_read(0x33a); + case 27: return rv_csr_read(0x33b); + case 28: return rv_csr_read(0x33c); + case 29: return rv_csr_read(0x33d); + case 30: return rv_csr_read(0x33e); + case 31: return rv_csr_read(0x33F); + default: return 0; + } +} + +/** + \brief Set MHPMEVENTH + \details Write MHPMEVENTH Register + \param [in] idx Index of MHPMEVENT Register + \param [in] value MHPMEVENTH Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MHPMEVENTH(unsigned long idx, unsigned long value) +{ + switch (idx) { + case 3: rv_csr_write(0x723, value); break; + case 4: rv_csr_write(0x724, value); break; + case 5: rv_csr_write(0x725, value); break; + case 6: rv_csr_write(0x726, value); break; + case 7: rv_csr_write(0x727, value); break; + case 8: rv_csr_write(0x728, value); break; + case 9: rv_csr_write(0x729, value); break; + case 10: rv_csr_write(0x72A, value); break; + case 11: rv_csr_write(0x72B, value); break; + case 12: rv_csr_write(0x72C, value); break; + case 13: rv_csr_write(0x72D, value); break; + case 14: rv_csr_write(0x72E, value); break; + case 15: rv_csr_write(0x72F, value); break; + case 16: rv_csr_write(0x730, value); break; + case 17: rv_csr_write(0x731, value); break; + case 18: rv_csr_write(0x732, value); break; + case 19: rv_csr_write(0x733, value); break; + case 20: rv_csr_write(0x734, value); break; + case 21: rv_csr_write(0x735, value); break; + case 22: rv_csr_write(0x736, value); break; + case 23: rv_csr_write(0x737, value); break; + case 24: rv_csr_write(0x738, value); break; + case 25: rv_csr_write(0x739, value); break; + case 26: rv_csr_write(0x73A, value); break; + case 27: rv_csr_write(0x73B, value); break; + case 28: rv_csr_write(0x73C, value); break; + case 29: rv_csr_write(0x73D, value); break; + case 30: rv_csr_write(0x73E, value); break; + case 31: rv_csr_write(0x73F, value); break; + default: break; + } +} + +/** + \brief Get MHPMEVENTH + \details Read MHPMEVENTH Register. + \param [in] idx Index of MHPMEVENTH Register to read. + \return MHPMEVENTH Register Value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHPMEVENTH(unsigned long idx) +{ + switch (idx) { + case 3: return rv_csr_read(0x723); + case 4: return rv_csr_read(0x724); + case 5: return rv_csr_read(0x725); + case 6: return rv_csr_read(0x726); + case 7: return rv_csr_read(0x727); + case 8: return rv_csr_read(0x728); + case 9: return rv_csr_read(0x729); + case 10: return rv_csr_read(0x72A); + case 11: return rv_csr_read(0x72B); + case 12: return rv_csr_read(0x72C); + case 13: return rv_csr_read(0x72D); + case 14: return rv_csr_read(0x72E); + case 15: return rv_csr_read(0x72F); + case 16: return rv_csr_read(0x730); + case 17: return rv_csr_read(0x731); + case 18: return rv_csr_read(0x732); + case 19: return rv_csr_read(0x733); + case 20: return rv_csr_read(0x734); + case 21: return rv_csr_read(0x735); + case 22: return rv_csr_read(0x736); + case 23: return rv_csr_read(0x737); + case 24: return rv_csr_read(0x738); + case 25: return rv_csr_read(0x739); + case 26: return rv_csr_read(0x73A); + case 27: return rv_csr_read(0x73B); + case 28: return rv_csr_read(0x73C); + case 29: return rv_csr_read(0x73D); + case 30: return rv_csr_read(0x73E); + case 31: return rv_csr_read(0x73F); + default: return 0; + } +} + +/** + \brief Set MHPMCOUNTER + \details Write MHPMCOUNTER Register + \param [in] idx Index of MHPMCOUNTER Register + \param [in] value MHPMCOUNTER Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MHPMCOUNTER(unsigned long idx, unsigned long value) +{ + switch (idx) { + case 3: rv_csr_write(0xB03, (value)); break; + case 4: rv_csr_write(0xB04, (value)); break; + case 5: rv_csr_write(0xB05, (value)); break; + case 6: rv_csr_write(0xB06, (value)); break; + case 7: rv_csr_write(0xB07, (value)); break; + case 8: rv_csr_write(0xB08, (value)); break; + case 9: rv_csr_write(0xB09, (value)); break; + case 10: rv_csr_write(0xB0A, (value)); break; + case 11: rv_csr_write(0xB0B, (value)); break; + case 12: rv_csr_write(0xB0C, (value)); break; + case 13: rv_csr_write(0xB0D, (value)); break; + case 14: rv_csr_write(0xB0E, (value)); break; + case 15: rv_csr_write(0xB0F, (value)); break; + case 16: rv_csr_write(0xB10, (value)); break; + case 17: rv_csr_write(0xB11, (value)); break; + case 18: rv_csr_write(0xB12, (value)); break; + case 19: rv_csr_write(0xB13, (value)); break; + case 20: rv_csr_write(0xB14, (value)); break; + case 21: rv_csr_write(0xB15, (value)); break; + case 22: rv_csr_write(0xB16, (value)); break; + case 23: rv_csr_write(0xB17, (value)); break; + case 24: rv_csr_write(0xB18, (value)); break; + case 25: rv_csr_write(0xB19, (value)); break; + case 26: rv_csr_write(0xB1A, (value)); break; + case 27: rv_csr_write(0xB1B, (value)); break; + case 28: rv_csr_write(0xB1C, (value)); break; + case 29: rv_csr_write(0xB1D, (value)); break; + case 30: rv_csr_write(0xB1E, (value)); break; + case 31: rv_csr_write(0xB1F, (value)); break; + default: break; + } +} + +/** + \brief Get MHPMCOUNTER + \details Write MHPMCOUNTER Register. + \param [in] idx Index of MHPMCOUNTER Register + \return MHPMCOUNTER Register Value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHPMCOUNTER(unsigned long idx) +{ + switch (idx) { + case 3: return rv_csr_read(0xB03); + case 4: return rv_csr_read(0xB04); + case 5: return rv_csr_read(0xB05); + case 6: return rv_csr_read(0xB06); + case 7: return rv_csr_read(0xB07); + case 8: return rv_csr_read(0xB08); + case 9: return rv_csr_read(0xB09); + case 10: return rv_csr_read(0xB0A); + case 11: return rv_csr_read(0xB0B); + case 12: return rv_csr_read(0xB0C); + case 13: return rv_csr_read(0xB0D); + case 14: return rv_csr_read(0xB0E); + case 15: return rv_csr_read(0xB0F); + case 16: return rv_csr_read(0xB10); + case 17: return rv_csr_read(0xB11); + case 18: return rv_csr_read(0xB12); + case 19: return rv_csr_read(0xB13); + case 20: return rv_csr_read(0xB14); + case 21: return rv_csr_read(0xB15); + case 22: return rv_csr_read(0xB16); + case 23: return rv_csr_read(0xB17); + case 24: return rv_csr_read(0xB18); + case 25: return rv_csr_read(0xB19); + case 26: return rv_csr_read(0xB1A); + case 27: return rv_csr_read(0xB1B); + case 28: return rv_csr_read(0xB1C); + case 29: return rv_csr_read(0xB1D); + case 30: return rv_csr_read(0xB1E); + case 31: return rv_csr_read(0xB1F); + default: return 0; + } +} + +/** + \brief Set MHPMCOUNTERH + \details Write MHPMCOUNTERH Register + \param [in] idx Index of MHPMCOUNTERH Register + \param [in] value MHPMCOUNTERH Register value to set + */ +__ALWAYS_STATIC_INLINE void __set_MHPMCOUNTERH(unsigned long idx, unsigned long value) +{ + switch (idx) { + case 3: rv_csr_write(0xB83, (value)); break; + case 4: rv_csr_write(0xB84, (value)); break; + case 5: rv_csr_write(0xB85, (value)); break; + case 6: rv_csr_write(0xB86, (value)); break; + case 7: rv_csr_write(0xB87, (value)); break; + case 8: rv_csr_write(0xB88, (value)); break; + case 9: rv_csr_write(0xB89, (value)); break; + case 10: rv_csr_write(0xB8A, (value)); break; + case 11: rv_csr_write(0xB8B, (value)); break; + case 12: rv_csr_write(0xB8C, (value)); break; + case 13: rv_csr_write(0xB8D, (value)); break; + case 14: rv_csr_write(0xB8E, (value)); break; + case 15: rv_csr_write(0xB8F, (value)); break; + case 16: rv_csr_write(0xB90, (value)); break; + case 17: rv_csr_write(0xB91, (value)); break; + case 18: rv_csr_write(0xB92, (value)); break; + case 19: rv_csr_write(0xB93, (value)); break; + case 20: rv_csr_write(0xB94, (value)); break; + case 21: rv_csr_write(0xB95, (value)); break; + case 22: rv_csr_write(0xB96, (value)); break; + case 23: rv_csr_write(0xB97, (value)); break; + case 24: rv_csr_write(0xB98, (value)); break; + case 25: rv_csr_write(0xB99, (value)); break; + case 26: rv_csr_write(0xB9A, (value)); break; + case 27: rv_csr_write(0xB9B, (value)); break; + case 28: rv_csr_write(0xB9C, (value)); break; + case 29: rv_csr_write(0xB9D, (value)); break; + case 30: rv_csr_write(0xB9E, (value)); break; + case 31: rv_csr_write(0xB9F, (value)); break; + default: break; + } +} + +/** + \brief Get MHPMCOUNTERH + \details Write MHPMCOUNTERH Register. + \param [in] idx Index of MHPMCOUNTERH Register + \return MHPMCOUNTERH Register Value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MHPMCOUNTERH(unsigned long idx) +{ + switch (idx) { + case 3: return rv_csr_read(0xB83); + case 4: return rv_csr_read(0xB84); + case 5: return rv_csr_read(0xB85); + case 6: return rv_csr_read(0xB86); + case 7: return rv_csr_read(0xB87); + case 8: return rv_csr_read(0xB88); + case 9: return rv_csr_read(0xB89); + case 10: return rv_csr_read(0xB8A); + case 11: return rv_csr_read(0xB8B); + case 12: return rv_csr_read(0xB8C); + case 13: return rv_csr_read(0xB8D); + case 14: return rv_csr_read(0xB8E); + case 15: return rv_csr_read(0xB8F); + case 16: return rv_csr_read(0xB90); + case 17: return rv_csr_read(0xB91); + case 18: return rv_csr_read(0xB92); + case 19: return rv_csr_read(0xB93); + case 20: return rv_csr_read(0xB94); + case 21: return rv_csr_read(0xB95); + case 22: return rv_csr_read(0xB96); + case 23: return rv_csr_read(0xB97); + case 24: return rv_csr_read(0xB98); + case 25: return rv_csr_read(0xB99); + case 26: return rv_csr_read(0xB9A); + case 27: return rv_csr_read(0xB9B); + case 28: return rv_csr_read(0xB9C); + case 29: return rv_csr_read(0xB9D); + case 30: return rv_csr_read(0xB9E); + case 31: return rv_csr_read(0xB9F); + default: return 0; + } +} + +#if 0 +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE unsigned long __REV(unsigned long value) +{ + return __builtin_bswap32(value); +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + result = ((value & 0xFF000000) >> 8) | ((value & 0x00FF0000) << 8) | + ((value & 0x0000FF00) >> 8) | ((value & 0x000000FF) << 8); + + return (result); +} + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE int32_t __REVSH(int32_t value) +{ + return (short)(((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8)); +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__ALWAYS_STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + */ +__ALWAYS_STATIC_INLINE void __BKPT(void) +{ + __ASM volatile("ebreak"); +} + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__ALWAYS_STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + + for (value >>= 1U; value; value >>= 1U) { + result <<= 1U; + result |= value & 1U; + s--; + } + + result <<= s; /* shift when v's highest bits are zero */ + + return (result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz +/** + \details This function saturates a signed value. + \param [in] x Value to be saturated + \param [in] y Bit position to saturate to [1..32] + \return Saturated value. + */ +__ALWAYS_STATIC_INLINE int32_t __SSAT(int32_t x, uint32_t y) +{ + int32_t posMax, negMin; + uint32_t i; + + posMax = 1; + + for (i = 0; i < (y - 1); i++) { + posMax = posMax * 2; + } + + if (x > 0) { + posMax = (posMax - 1); + + if (x > posMax) { + x = posMax; + } + +// x &= (posMax * 2 + 1); + } else { + negMin = -posMax; + + if (x < negMin) { + x = negMin; + } + +// x &= (posMax * 2 - 1); + } + + return (x); +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__ALWAYS_STATIC_INLINE uint32_t __USAT(uint32_t value, uint32_t sat) +{ + uint32_t result; + + if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) { + result = 0xFFFFFFFF >> (32 - sat); + } else { + result = value; + } + + return (result); +} + +/** + \brief Unsigned Saturate for internal use + \details Saturates an unsigned value, should not call directly. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__ALWAYS_STATIC_INLINE uint32_t __IUSAT(uint32_t value, uint32_t sat) +{ + uint32_t result; + + if (value & 0x80000000) { /* only overflow set bit-31 */ + result = 0; + } else if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) { + result = 0xFFFFFFFF >> (32 - sat); + } else { + result = value; + } + + return (result); +} + +/** + \brief Rotate Right with Extend + \details This function moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \note carry input will always 0. + \param [in] op1 Value to rotate + \return Rotated value + */ +__ALWAYS_STATIC_INLINE uint32_t __RRX(uint32_t op1) +{ + return 0; +} + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] addr Pointer to location + \return value of type uint8_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile("lb %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] addr Pointer to location + \return value of type uint16_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile("lh %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] addr Pointer to location + \return value of type uint32_t at (*ptr) + */ +__ALWAYS_STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile("lw %0, 0(%1)" : "=r"(result) : "r"(addr)); + + return (result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) +{ + __ASM volatile("sb %1, 0(%0)" :: "r"(addr), "r"((uint32_t)value) : "memory"); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) +{ + __ASM volatile("sh %1, 0(%0)" :: "r"(addr), "r"((uint32_t)value) : "memory"); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] addr Pointer to location + */ +__ALWAYS_STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) +{ + __ASM volatile("sw %1, 0(%0)" :: "r"(addr), "r"(value) : "memory"); +} + +/*@}*/ /* end of group CSI_Core_InstructionInterface */ + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CSI_SIMD_intrinsics CSI SIMD Intrinsics + Access to dedicated SIMD instructions \n + Single Instruction Multiple Data (SIMD) extensions are provided to simplify development of application software. SIMD extensions increase the processing capability without materially increasing the power consumption. The SIMD extensions are completely transparent to the operating system (OS), allowing existing OS ports to be used. + + @{ +*/ + +/** + \brief Halfword packing instruction. Combines bits[15:0] of val1 with bits[31:16] + of val2 levitated with the val3. + \details Combine a halfword from one register with a halfword from another register. + The second argument can be left-shifted before extraction of the halfword. + \param [in] val1 first 16-bit operands + \param [in] val2 second 16-bit operands + \param [in] val3 value for left-shifting val2. Value range [0..31]. + \return the combination of halfwords. + \remark + res[15:0] = val1[15:0] \n + res[31:16] = val2[31:16] << val3 + */ +__ALWAYS_STATIC_INLINE uint32_t __PKHBT(uint32_t val1, uint32_t val2, uint32_t val3) +{ + return ((((int32_t)(val1) << 0) & (int32_t)0x0000FFFF) | (((int32_t)(val2) << val3) & (int32_t)0xFFFF0000)); +} + +/** + \brief Halfword packing instruction. Combines bits[31:16] of val1 with bits[15:0] + of val2 right-shifted with the val3. + \details Combine a halfword from one register with a halfword from another register. + The second argument can be right-shifted before extraction of the halfword. + \param [in] val1 first 16-bit operands + \param [in] val2 second 16-bit operands + \param [in] val3 value for right-shifting val2. Value range [1..32]. + \return the combination of halfwords. + \remark + res[15:0] = val2[15:0] >> val3 \n + res[31:16] = val1[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __PKHTB(uint32_t val1, uint32_t val2, uint32_t val3) +{ + return ((((int32_t)(val1) << 0) & (int32_t)0xFFFF0000) | (((int32_t)(val2) >> val3) & (int32_t)0x0000FFFF)); +} + +/** + \brief Dual 16-bit signed saturate. + \details This function saturates a signed value. + \param [in] x two signed 16-bit values to be saturated. + \param [in] y bit position for saturation, an integral constant expression in the range 1 to 16. + \return the sum of the absolute differences of the following bytes, added to the accumulation value:\n + the signed saturation of the low halfword in val1, saturated to the bit position specified in + val2 and returned in the low halfword of the return value.\n + the signed saturation of the high halfword in val1, saturated to the bit position specified in + val2 and returned in the high halfword of the return value. + */ +__ALWAYS_STATIC_INLINE uint32_t __SSAT16(int32_t x, const uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __SSAT((((int32_t)x << 16) >> 16), y) & (int32_t)0x0000FFFF; + s = __SSAT((((int32_t)x) >> 16), y) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturate. + \details This function enables you to saturate two signed 16-bit values to a selected unsigned range. + \param [in] x two signed 16-bit values to be saturated. + \param [in] y bit position for saturation, an integral constant expression in the range 1 to 16. + \return the saturation of the two signed 16-bit values, as non-negative values: + the saturation of the low halfword in val1, saturated to the bit position specified in + val2 and returned in the low halfword of the return value.\n + the saturation of the high halfword in val1, saturated to the bit position specified in + val2 and returned in the high halfword of the return value. + */ +__ALWAYS_STATIC_INLINE uint32_t __USAT16(uint32_t x, const uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __IUSAT(((x << 16) >> 16), y) & 0x0000FFFF; + s = __IUSAT(((x) >> 16), y) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit saturating addition. + \details This function enables you to perform four 8-bit integer additions, + saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the saturated addition of the first byte of each operand in the first byte of the return value.\n + the saturated addition of the second byte of each operand in the second byte of the return value.\n + the saturated addition of the third byte of each operand in the third byte of the return value.\n + the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __QADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __SSAT(((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((int32_t)x) >> 24) + (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned saturating addition. + \details This function enables you to perform four unsigned 8-bit integer additions, + saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the saturated addition of the first byte of each operand in the first byte of the return value.\n + the saturated addition of the second byte of each operand in the second byte of the return value.\n + the saturated addition of the third byte of each operand in the third byte of the return value.\n + the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range 0 <= x <= 2^8 - 1. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __IUSAT((((x << 24) >> 24) + ((y << 24) >> 24)), 8) & 0x000000FF; + s = __IUSAT((((x << 16) >> 24) + ((y << 16) >> 24)), 8) & 0x000000FF; + t = __IUSAT((((x << 8) >> 24) + ((y << 8) >> 24)), 8) & 0x000000FF; + u = __IUSAT((((x) >> 24) + ((y) >> 24)), 8) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit signed addition. + \details This function performs four 8-bit signed integer additions. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the addition of the first bytes from each operand, in the first byte of the return value.\n + the addition of the second bytes of each operand, in the second byte of the return value.\n + the addition of the third bytes of each operand, in the third byte of the return value.\n + the addition of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __SADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF; + s = ((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF; + t = ((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)) & (int32_t)0x000000FF; + u = ((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned addition. + \details This function performs four unsigned 8-bit integer additions. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the addition of the first bytes from each operand, in the first byte of the return value.\n + the addition of the second bytes of each operand, in the second byte of the return value.\n + the addition of the third bytes of each operand, in the third byte of the return value.\n + the addition of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] + val2[7:0] \n + res[15:8] = val1[15:8] + val2[15:8] \n + res[23:16] = val1[23:16] + val2[23:16] \n + res[31:24] = val1[31:24] + val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) + ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) + ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) + ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) + ((y) >> 24)) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit saturating subtract. + \details This function enables you to perform four 8-bit integer subtractions, + saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the subtraction of the first byte of each operand in the first byte of the return value.\n + the subtraction of the second byte of each operand in the second byte of the return value.\n + the subtraction of the third byte of each operand in the third byte of the return value.\n + the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __SSAT(((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((int32_t)x) >> 24) - (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned saturating subtraction. + \details This function enables you to perform four unsigned 8-bit integer subtractions, + saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the subtraction of the first byte of each operand in the first byte of the return value.\n + the subtraction of the second byte of each operand in the second byte of the return value.\n + the subtraction of the third byte of each operand in the third byte of the return value.\n + the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n + The returned results are saturated to the 8-bit unsigned integer range 0 <= x <= 2^8 - 1. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = __IUSAT((((x << 24) >> 24) - ((y << 24) >> 24)), 8) & 0x000000FF; + s = __IUSAT((((x << 16) >> 24) - ((y << 16) >> 24)), 8) & 0x000000FF; + t = __IUSAT((((x << 8) >> 24) - ((y << 8) >> 24)), 8) & 0x000000FF; + u = __IUSAT((((x) >> 24) - ((y) >> 24)), 8) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Quad 8-bit signed subtraction. + \details This function enables you to perform four 8-bit signed integer subtractions. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF; + s = ((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF; + t = ((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)) & (int32_t)0x000000FF; + u = ((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned subtract. + \details This function enables you to perform four 8-bit unsigned integer subtractions. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + res[7:0] = val1[7:0] - val2[7:0] \n + res[15:8] = val1[15:8] - val2[15:8] \n + res[23:16] = val1[23:16] - val2[23:16] \n + res[31:24] = val1[31:24] - val2[31:24] + */ +__ALWAYS_STATIC_INLINE uint32_t __USUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) - ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Unsigned sum of quad 8-bit unsigned absolute difference. + \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values + of the differences together, returning the result as a single unsigned integer. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \return the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value.\n + The sum is returned as a single unsigned integer. + \remark + absdiff1 = val1[7:0] - val2[7:0] \n + absdiff2 = val1[15:8] - val2[15:8] \n + absdiff3 = val1[23:16] - val2[23:16] \n + absdiff4 = val1[31:24] - val2[31:24] \n + res[31:0] = absdiff1 + absdiff2 + absdiff3 + absdiff4 + */ +__ALWAYS_STATIC_INLINE uint32_t __USAD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF; + s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF; + t = (((x << 8) >> 24) - ((y << 8) >> 24)) & 0x000000FF; + u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF; + + return (u + t + s + r); +} + +/** + \brief Unsigned sum of quad 8-bit unsigned absolute difference with 32-bit accumulate. + \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values + of the differences to a 32-bit accumulate operand. + \param [in] x first four 8-bit operands of each subtraction. + \param [in] y second four 8-bit operands of each subtraction. + \param [in] sum accumulation value. + \return the sum of the absolute differences of the following bytes, added to the accumulation value: + the subtraction of the first bytes from each operand, in the first byte of the return value.\n + the subtraction of the second bytes of each operand, in the second byte of the return value.\n + the subtraction of the third bytes of each operand, in the third byte of the return value.\n + the subtraction of the fourth bytes of each operand, in the fourth byte of the return value. + \remark + absdiff1 = val1[7:0] - val2[7:0] \n + absdiff2 = val1[15:8] - val2[15:8] \n + absdiff3 = val1[23:16] - val2[23:16] \n + absdiff4 = val1[31:24] - val2[31:24] \n + sum = absdiff1 + absdiff2 + absdiff3 + absdiff4 \n + res[31:0] = sum[31:0] + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __USADA8(uint32_t x, uint32_t y, uint32_t sum) +{ + int32_t r, s, t, u; + +#ifdef __cplusplus + r = (abs((long long)((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF; + s = (abs((long long)((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF; + t = (abs((long long)((x << 8) >> 24) - ((y << 8) >> 24))) & 0x000000FF; + u = (abs((long long)((x) >> 24) - ((y) >> 24))) & 0x000000FF; +#else + r = (abs(((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF; + s = (abs(((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF; + t = (abs(((x << 8) >> 24) - ((y << 8) >> 24))) & 0x000000FF; + u = (abs(((x) >> 24) - ((y) >> 24))) & 0x000000FF; +#endif + return (u + t + s + r + sum); +} + +/** + \brief Dual 16-bit saturating addition. + \details This function enables you to perform two 16-bit integer arithmetic additions in parallel, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated addition of the low halfwords, in the low halfword of the return value.\n + the saturated addition of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __QADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating addition. + \details This function enables you to perform two unsigned 16-bit integer additions, saturating + the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated addition of the low halfwords, in the low halfword of the return value.\n + the saturated addition of the high halfwords, in the high halfword of the return value.\n + The results are saturated to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = __IUSAT((((x << 16) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed addition. + \details This function enables you to perform two 16-bit signed integer additions. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the addition of the low halfwords in the low halfword of the return value.\n + the addition of the high halfwords in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __SADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = ((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition + \details This function enables you to perform two 16-bit unsigned integer additions. + \param [in] x first two 16-bit summands for each addition. + \param [in] y second two 16-bit summands for each addition. + \return the addition of the low halfwords in the low halfword of the return value.\n + the addition of the high halfwords in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] + val2[15:0] \n + res[31:16] = val1[31:16] + val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UADD16(uint32_t x, uint32_t y) +{ + int32_t r = 0, s = 0; + + r = (((x << 16) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) + ((y) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + + +/** + \brief Dual 16-bit signed addition with halved results. + \details This function enables you to perform two signed 16-bit integer additions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved addition of the low halfwords, in the low halfword of the return value.\n + the halved addition of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] + val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHADD16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition with halved results. + \details This function enables you to perform two unsigned 16-bit integer additions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved addition of the low halfwords, in the low halfword of the return value.\n + the halved addition of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] + val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHADD16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit signed addition with halved results. + \details This function enables you to perform four signed 8-bit integer additions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved addition of the first bytes from each operand, in the first byte of the return value.\n + the halved addition of the second bytes from each operand, in the second byte of the return value.\n + the halved addition of the third bytes from each operand, in the third byte of the return value.\n + the halved addition of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] + val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] + val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] + val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] + val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF; + s = (((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF; + t = (((((int32_t)x << 8) >> 24) + (((int32_t)y << 8) >> 24)) >> 1) & (int32_t)0x000000FF; + u = (((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned addition with halved results. + \details This function enables you to perform four unsigned 8-bit integer additions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved addition of the first bytes from each operand, in the first byte of the return value.\n + the halved addition of the second bytes from each operand, in the second byte of the return value.\n + the halved addition of the third bytes from each operand, in the third byte of the return value.\n + the halved addition of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] + val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] + val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] + val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] + val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHADD8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((x << 24) >> 24) + ((y << 24) >> 24)) >> 1) & 0x000000FF; + s = ((((x << 16) >> 24) + ((y << 16) >> 24)) >> 1) & 0x000000FF; + t = ((((x << 8) >> 24) + ((y << 8) >> 24)) >> 1) & 0x000000FF; + u = ((((x) >> 24) + ((y) >> 24)) >> 1) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Dual 16-bit saturating subtract. + \details This function enables you to perform two 16-bit integer subtractions in parallel, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the saturated subtraction of the low halfwords, in the low halfword of the return value.\n + the saturated subtraction of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating subtraction. + \details This function enables you to perform two unsigned 16-bit integer subtractions, + saturating the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1. + \param [in] x first two 16-bit operands for each subtraction. + \param [in] y second two 16-bit operands for each subtraction. + \return the saturated subtraction of the low halfwords, in the low halfword of the return value.\n + the saturated subtraction of the high halfwords, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction. + \details This function enables you to perform two 16-bit signed integer subtractions. + \param [in] x first two 16-bit operands of each subtraction. + \param [in] y second two 16-bit operands of each subtraction. + \return the subtraction of the low halfword in the second operand from the low + halfword in the first operand, in the low halfword of the return value. \n + the subtraction of the high halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtract. + \details This function enables you to perform two 16-bit unsigned integer subtractions. + \param [in] x first two 16-bit operands of each subtraction. + \param [in] y second two 16-bit operands of each subtraction. + \return the subtraction of the low halfword in the second operand from the low + halfword in the first operand, in the low halfword of the return value. \n + the subtraction of the high halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[15:0] \n + res[31:16] = val1[31:16] - val2[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __USUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) - ((y) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction with halved results. + \details This function enables you to perform two signed 16-bit integer subtractions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved subtraction of the low halfwords, in the low halfword of the return value.\n + the halved subtraction of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] - val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtraction with halved results. + \details This function enables you to perform two unsigned 16-bit integer subtractions, halving the results. + \param [in] x first two 16-bit summands. + \param [in] y second two 16-bit summands. + \return the halved subtraction of the low halfwords, in the low halfword of the return value.\n + the halved subtraction of the high halfwords, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[15:0]) >> 1 \n + res[31:16] = (val1[31:16] - val2[31:16]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSUB16(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Quad 8-bit signed addition with halved results. + \details This function enables you to perform four signed 8-bit integer subtractions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n + the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n + the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n + the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] - val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] - val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] - val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] - val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = (((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF; + s = (((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF; + t = (((((int32_t)x << 8) >> 24) - (((int32_t)y << 8) >> 24)) >> 1) & (int32_t)0x000000FF; + u = (((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r))); +} + +/** + \brief Quad 8-bit unsigned subtraction with halved results. + \details This function enables you to perform four unsigned 8-bit integer subtractions, halving the results. + \param [in] x first four 8-bit summands. + \param [in] y second four 8-bit summands. + \return the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n + the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n + the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n + the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value. + \remark + res[7:0] = (val1[7:0] - val2[7:0] ) >> 1 \n + res[15:8] = (val1[15:8] - val2[15:8] ) >> 1 \n + res[23:16] = (val1[23:16] - val2[23:16]) >> 1 \n + res[31:24] = (val1[31:24] - val2[31:24]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSUB8(uint32_t x, uint32_t y) +{ + int32_t r, s, t, u; + + r = ((((x << 24) >> 24) - ((y << 24) >> 24)) >> 1) & 0x000000FF; + s = ((((x << 16) >> 24) - ((y << 16) >> 24)) >> 1) & 0x000000FF; + t = ((((x << 8) >> 24) - ((y << 8) >> 24)) >> 1) & 0x000000FF; + u = ((((x) >> 24) - ((y) >> 24)) >> 1) & 0x000000FF; + + return ((u << 24) | (t << 16) | (s << 8) | (r)); +} + +/** + \brief Dual 16-bit add and subtract with exchange. + \details This function enables you to exchange the halfwords of the one operand, + then add the high halfwords and subtract the low halfwords, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the saturated subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the saturated addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __QASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating addition and subtraction with exchange. + \details This function enables you to exchange the halfwords of the second operand and + perform one unsigned 16-bit integer addition and one unsigned 16-bit subtraction, + saturating the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the saturated subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the saturated addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit addition and subtraction with exchange. + \details It enables you to exchange the halfwords of the second operand, add the high halfwords + and subtract the low halfwords. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition and subtraction with exchange. + \details This function enables you to exchange the two halfwords of the second operand, + add the high halfwords and subtract the low halfwords. + \param [in] x first operand for the subtraction in the low halfword, + and the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, + and the second operand for the addition in the low halfword. + \return the subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the addition of the high halfword in the first operand and the + low halfword in the second operand, in the high halfword of the return value. + \remark + res[15:0] = val1[15:0] - val2[31:16] \n + res[31:16] = val1[31:16] + val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) - ((y) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed addition and subtraction with halved results. + \details This function enables you to exchange the two halfwords of one operand, perform one + signed 16-bit integer addition and one signed 16-bit subtraction, and halve the results. + \param [in] x first 16-bit operands. + \param [in] y second 16-bit operands. + \return the halved subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the halved addition of the low halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] + val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned addition and subtraction with halved results and exchange. + \details This function enables you to exchange the halfwords of the second operand, + add the high halfwords and subtract the low halfwords, halving the results. + \param [in] x first operand for the subtraction in the low halfword, and + the first operand for the addition in the high halfword. + \param [in] y second operand for the subtraction in the high halfword, and + the second operand for the addition in the low halfword. + \return the halved subtraction of the high halfword in the second operand from the + low halfword in the first operand, in the low halfword of the return value.\n + the halved addition of the low halfword in the second operand from the high + halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] - val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] + val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHASX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit subtract and add with exchange. + \details This function enables you to exchange the halfwords of one operand, + then subtract the high halfwords and add the low halfwords, + saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the saturated addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the saturated subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1. + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __QSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned saturating subtraction and addition with exchange. + \details This function enables you to exchange the halfwords of the second operand and perform + one unsigned 16-bit integer subtraction and one unsigned 16-bit addition, saturating + the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the saturated addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the saturated subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1. + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __UQSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = __IUSAT((((x << 16) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF; + s = __IUSAT((((x) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit unsigned subtract and add with exchange. + \details This function enables you to exchange the halfwords of the second operand, + subtract the high halfwords and add the low halfwords. + \param [in] x first operand for the addition in the low halfword, + and the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, + and the second operand for the subtraction in the low halfword. + \return the addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __USAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((x << 16) >> 16) + ((y) >> 16)) & 0x0000FFFF; + s = (((x) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed subtraction and addition with exchange. + \details This function enables you to exchange the two halfwords of one operand and perform one + 16-bit integer subtraction and one 16-bit addition. + \param [in] x first operand for the addition in the low halfword, and the first operand + for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, and the second + operand for the subtraction in the low halfword. + \return the addition of the low halfword of the first operand and the high + halfword of the second operand, in the low halfword of the return value.\n + the subtraction of the low halfword of the second operand from the + high halfword of the first operand, in the high halfword of the return value.\n + \remark + res[15:0] = val1[15:0] + val2[31:16] \n + res[31:16] = val1[31:16] - val2[15:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF; + s = ((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + + +/** + \brief Dual 16-bit signed subtraction and addition with halved results. + \details This function enables you to exchange the two halfwords of one operand, perform one signed + 16-bit integer subtraction and one signed 16-bit addition, and halve the results. + \param [in] x first 16-bit operands. + \param [in] y second 16-bit operands. + \return the halved addition of the low halfword in the first operand and the + high halfword in the second operand, in the low halfword of the return value.\n + the halved subtraction of the low halfword in the second operand from the + high halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] - val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __SHSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = (((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r))); +} + +/** + \brief Dual 16-bit unsigned subtraction and addition with halved results and exchange. + \details This function enables you to exchange the halfwords of the second operand, + subtract the high halfwords and add the low halfwords, halving the results. + \param [in] x first operand for the addition in the low halfword, and + the first operand for the subtraction in the high halfword. + \param [in] y second operand for the addition in the high halfword, and + the second operand for the subtraction in the low halfword. + \return the halved addition of the low halfword in the first operand and the + high halfword in the second operand, in the low halfword of the return value.\n + the halved subtraction of the low halfword in the second operand from the + high halfword in the first operand, in the high halfword of the return value. + \remark + res[15:0] = (val1[15:0] + val2[31:16]) >> 1 \n + res[31:16] = (val1[31:16] - val2[15:0]) >> 1 + */ +__ALWAYS_STATIC_INLINE uint32_t __UHSAX(uint32_t x, uint32_t y) +{ + int32_t r, s; + + r = ((((x << 16) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF; + s = ((((x) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF; + + return ((s << 16) | (r)); +} + +/** + \brief Dual 16-bit signed multiply with exchange returning difference. + \details This function enables you to perform two 16-bit signed multiplications, subtracting + one of the products from the other. The halfwords of the second operand are exchanged + before performing the arithmetic. This produces top * bottom and bottom * top multiplication. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the difference of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 - p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUSDX(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)))); +} + +/** + \brief Sum of dual 16-bit signed multiply with exchange. + \details This function enables you to perform two 16-bit signed multiplications with exchanged + halfwords of the second operand, adding the products together. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the sum of the products of the two 16-bit signed multiplications with exchanged halfwords of the second operand. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 + p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUADX(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)))); +} + + +/** + \brief Saturating add. + \details This function enables you to obtain the saturating add of two integers. + \param [in] x first summand of the saturating add operation. + \param [in] y second summand of the saturating add operation. + \return the saturating addition of val1 and val2. + \remark + res[31:0] = SAT(val1 + SAT(val2)) + */ +__ALWAYS_STATIC_INLINE int32_t __QADD(int32_t x, int32_t y) +{ + int32_t result; + + if (y >= 0) { + if ((int32_t)((uint32_t)x + (uint32_t)y) >= x) { + result = x + y; + } else { + result = 0x7FFFFFFF; + } + } else { + if ((int32_t)((uint32_t)x + (uint32_t)y) < x) { + result = x + y; + } else { + result = 0x80000000; + } + } + + return result; +} + +/** + \brief Saturating subtract. + \details This function enables you to obtain the saturating add of two integers. + \param [in] x first summand of the saturating add operation. + \param [in] y second summand of the saturating add operation. + \return the saturating addition of val1 and val2. + \remark + res[31:0] = SAT(val1 - SAT(val2)) + */ +__ALWAYS_STATIC_INLINE int32_t __QSUB(int32_t x, int32_t y) +{ + long tmp; + int32_t result; + + tmp = (long)x - (long)y; + + if (tmp > 0x7fffffff) { + tmp = 0x7fffffff; + } else if (tmp < (-2147483647 - 1)) { + tmp = -2147483647 - 1; + } + + result = tmp; + return result; +} + +/** + \brief Dual 16-bit signed multiply with single 32-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications, + adding both results to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value, as a 32-bit integer. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 + p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLAD(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Pre-exchanged dual 16-bit signed multiply with single 32-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications with exchanged + halfwords of the second operand, adding both results to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication with exchanged halfwords of the second + operand added to the accumulate value, as a 32-bit integer. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 + p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLADX(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate. + \details This function enables you to perform two 16-bit signed multiplications, take the + difference of the products, subtracting the high halfword product from the low + halfword product, and add the difference to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 - p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLSD(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate. + \details This function enables you to exchange the halfwords in the second operand, then perform two 16-bit + signed multiplications. The difference of the products is added to a 32-bit accumulate operand. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[31:0] = p1 - p2 + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMLSDX(uint32_t x, uint32_t y, uint32_t sum) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((int32_t)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with single 64-bit accumulator. + \details This function enables you to perform two signed 16-bit multiplications, adding both results + to a 64-bit accumulate operand. Overflow is only possible as a result of the 64-bit addition. + This overflow is not detected if it occurs. Instead, the result wraps around modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + sum = p1 + p2 + val3[63:32][31:0] \n + res[63:32] = sum[63:32] \n + res[31:0] = sum[31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLALD(uint32_t x, uint32_t y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((unsigned long)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange with single 64-bit accumulator. + \details This function enables you to exchange the halfwords of the second operand, and perform two + signed 16-bit multiplications, adding both results to a 64-bit accumulate operand. Overflow + is only possible as a result of the 64-bit addition. This overflow is not detected if it occurs. + Instead, the result wraps around modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the product of each multiplication added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + sum = p1 + p2 + val3[63:32][31:0] \n + res[63:32] = sum[63:32] \n + res[31:0] = sum[31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLALDX(uint32_t x, uint32_t y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((unsigned long)sum)))); +} + +/** + \brief dual 16-bit signed multiply subtract with 64-bit accumulate. + \details This function It enables you to perform two 16-bit signed multiplications, take the difference + of the products, subtracting the high halfword product from the low halfword product, and add the + difference to a 64-bit accumulate operand. Overflow cannot occur during the multiplications or the + subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow is not + detected. Instead, the result wraps round to modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[63:32][31:0] = p1 - p2 + val3[63:32][31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLSLD(uint32_t x, uint32_t y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) + + (((unsigned long)sum)))); +} + +/** + \brief Dual 16-bit signed multiply with exchange subtract with 64-bit accumulate. + \details This function enables you to exchange the halfwords of the second operand, perform two 16-bit multiplications, + adding the difference of the products to a 64-bit accumulate operand. Overflow cannot occur during the + multiplications or the subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow + is not detected. Instead, the result wraps round to modulo2^64. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \param [in] sum accumulate value. + \return the difference of the product of each multiplication, added to the accumulate value. + \remark + p1 = val1[15:0] * val2[31:16] \n + p2 = val1[31:16] * val2[15:0] \n + res[63:32][31:0] = p1 - p2 + val3[63:32][31:0] + */ +__ALWAYS_STATIC_INLINE unsigned long __SMLSLDX(uint32_t x, uint32_t y, unsigned long sum) +{ + return ((unsigned long)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) + + (((unsigned long)sum)))); +} + +/** + \brief 32-bit signed multiply with 32-bit truncated accumulator. + \details This function enables you to perform a signed 32-bit multiplications, adding the most + significant 32 bits of the 64-bit result to a 32-bit accumulate operand. + \param [in] x first operand for multiplication. + \param [in] y second operand for multiplication. + \param [in] sum accumulate value. + \return the product of multiplication (most significant 32 bits) is added to the accumulate value, as a 32-bit integer. + \remark + p = val1 * val2 \n + res[31:0] = p[63:32] + val3[31:0] + */ +__ALWAYS_STATIC_INLINE uint32_t __SMMLA(int32_t x, int32_t y, int32_t sum) +{ + return (uint32_t)((int32_t)((long)((long)x * (long)y) >> 32) + sum); +} + +/** + \brief Sum of dual 16-bit signed multiply. + \details This function enables you to perform two 16-bit signed multiplications, adding the products together. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the sum of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 + p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUAD(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) + + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)))); +} + +/** + \brief Dual 16-bit signed multiply returning difference. + \details This function enables you to perform two 16-bit signed multiplications, taking the difference + of the products by subtracting the high halfword product from the low halfword product. + \param [in] x first 16-bit operands for each multiplication. + \param [in] y second 16-bit operands for each multiplication. + \return the difference of the products of the two 16-bit signed multiplications. + \remark + p1 = val1[15:0] * val2[15:0] \n + p2 = val1[31:16] * val2[31:16] \n + res[31:0] = p1 - p2 + */ +__ALWAYS_STATIC_INLINE uint32_t __SMUSD(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) - + ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)))); +} + +/** + \brief Dual extracted 8-bit to 16-bit signed addition. + \details This function enables you to extract two 8-bit values from the second operand (at bit positions + [7:0] and [23:16]), sign-extend them to 16-bits each, and add the results to the first operand. + \param [in] x values added to the sign-extended to 16-bit values. + \param [in] y two 8-bit values to be extracted and sign-extended. + \return the addition of val1 and val2, where the 8-bit values in val2[7:0] and + val2[23:16] have been extracted and sign-extended prior to the addition. + \remark + res[15:0] = val1[15:0] + SignExtended(val2[7:0]) \n + res[31:16] = val1[31:16] + SignExtended(val2[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __SXTAB16(uint32_t x, uint32_t y) +{ + return ((uint32_t)((((((int32_t)y << 24) >> 24) + (((int32_t)x << 16) >> 16)) & (int32_t)0x0000FFFF) | + (((((int32_t)y << 8) >> 8) + (((int32_t)x >> 16) << 16)) & (int32_t)0xFFFF0000))); +} + +/** + \brief Extracted 16-bit to 32-bit unsigned addition. + \details This function enables you to extract two 8-bit values from one operand, zero-extend + them to 16 bits each, and add the results to two 16-bit values from another operand. + \param [in] x values added to the zero-extended to 16-bit values. + \param [in] y two 8-bit values to be extracted and zero-extended. + \return the addition of val1 and val2, where the 8-bit values in val2[7:0] and + val2[23:16] have been extracted and zero-extended prior to the addition. + \remark + res[15:0] = ZeroExt(val2[7:0] to 16 bits) + val1[15:0] \n + res[31:16] = ZeroExt(val2[31:16] to 16 bits) + val1[31:16] + */ +__ALWAYS_STATIC_INLINE uint32_t __UXTAB16(uint32_t x, uint32_t y) +{ + return ((uint32_t)(((((y << 24) >> 24) + ((x << 16) >> 16)) & 0x0000FFFF) | + ((((y << 8) >> 8) + ((x >> 16) << 16)) & 0xFFFF0000))); +} + +/** + \brief Dual extract 8-bits and sign extend each to 16-bits. + \details This function enables you to extract two 8-bit values from an operand and sign-extend them to 16 bits each. + \param [in] x two 8-bit values in val[7:0] and val[23:16] to be sign-extended. + \return the 8-bit values sign-extended to 16-bit values.\n + sign-extended value of val[7:0] in the low halfword of the return value.\n + sign-extended value of val[23:16] in the high halfword of the return value. + \remark + res[15:0] = SignExtended(val[7:0]) \n + res[31:16] = SignExtended(val[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __SXTB16(uint32_t x) +{ + return ((uint32_t)(((((int32_t)x << 24) >> 24) & (int32_t)0x0000FFFF) | + ((((int32_t)x << 8) >> 8) & (int32_t)0xFFFF0000))); +} + +/** + \brief Dual extract 8-bits and zero-extend to 16-bits. + \details This function enables you to extract two 8-bit values from an operand and zero-extend them to 16 bits each. + \param [in] x two 8-bit values in val[7:0] and val[23:16] to be zero-extended. + \return the 8-bit values sign-extended to 16-bit values.\n + sign-extended value of val[7:0] in the low halfword of the return value.\n + sign-extended value of val[23:16] in the high halfword of the return value. + \remark + res[15:0] = SignExtended(val[7:0]) \n + res[31:16] = SignExtended(val[23:16]) + */ +__ALWAYS_STATIC_INLINE uint32_t __UXTB16(uint32_t x) +{ + return ((uint32_t)((((x << 24) >> 24) & 0x0000FFFF) | + (((x << 8) >> 8) & 0xFFFF0000))); +} +#endif + +#endif /* _CSI_RV32_GCC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv_common.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv_common.h new file mode 100644 index 00000000000..c2ebf23a79a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/core/csi_rv_common.h @@ -0,0 +1,129 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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 __CSI_RV_COMMON_H__ +#define __CSI_RV_COMMON_H__ + +#include +#include + +#ifndef __ASM +#define __ASM __asm /*!< asm keyword for GNU Compiler */ +#endif + +#ifndef __INLINE +#define __INLINE inline /*!< inline keyword for GNU Compiler */ +#endif + +#ifndef __ALWAYS_STATIC_INLINE +#define __ALWAYS_STATIC_INLINE __attribute__((always_inline)) static inline +#endif + +#ifndef __STATIC_INLINE +#define __STATIC_INLINE static inline +#endif + +#ifndef __NO_RETURN +#define __NO_RETURN __attribute__((__noreturn__)) +#endif + +#ifndef __USED +#define __USED __attribute__((used)) +#endif + +#ifndef __WEAK +#define __WEAK __attribute__((weak)) +#endif + +#ifndef __PACKED +#define __PACKED __attribute__((packed, aligned(1))) +#endif + +#ifndef __PACKED_STRUCT +#define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif + +#ifndef __PACKED_UNION +#define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif + +#ifdef __ASSEMBLY__ +#define __ASM_STR(x) x +#else +#define __ASM_STR(x) #x +#endif + +#ifndef __ASSEMBLY__ +#define rv_csr_read(csr) \ + ({ \ + register unsigned long __v; \ + __asm__ __volatile__("csrr %0, " __ASM_STR(csr) \ + : "=r"(__v) \ + : \ + : "memory"); \ + __v; \ + }) + +#define rv_csr_write(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__("csrw " __ASM_STR(csr) ", %0" \ + : \ + : "rK"(__v) \ + : "memory"); \ + }) + +#define rv_csr_read_set(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__("csrrs %0, " __ASM_STR(csr) ", %1" \ + : "=r"(__v) : "rK"(__v) \ + : "memory"); \ + __v; \ + }) + +#define rv_csr_set(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__("csrs " __ASM_STR(csr) ", %0" \ + : : "rK"(__v) \ + : "memory"); \ + }) + +#define rv_csr_read_clear(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__("csrrc %0, " __ASM_STR(csr) ", %1" \ + : "=r"(__v) : "rK"(__v) \ + : "memory"); \ + __v; \ + }) + +#define rv_csr_clear(csr, val) \ + ({ \ + unsigned long __v = (unsigned long)(val); \ + __asm__ __volatile__("csrc " __ASM_STR(csr) ", %0" \ + : : "rK"(__v) \ + : "memory"); \ + }) +#endif + + + +#endif /* __CSI_RV_COMMON_H__ */ + diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/csi_core.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/csi_core.h new file mode 100644 index 00000000000..85fe3408211 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/csi_core.h @@ -0,0 +1,186 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + + +/****************************************************************************** + * @file csi_core.h + * @brief CSI Core Layer Header File + * @version V1.0 + * @date 02. June 2017 + ******************************************************************************/ + +#ifndef _CORE_H_ +#define _CORE_H_ + +#include + +#if defined(__csky__) + +#if defined(__CK801__) || defined(__E801__) +#include +#elif defined(__CK802__) || defined(__E802__) || defined(__E802T__) || defined(__S802__) || defined(__S802T__) +#include +#elif defined(__CK804__) || defined(__E804D__) || defined(__E804DT__) || defined(__E804F__) || defined(__E804FT__) || defined (__E804DF__) || defined(__E804DFT__) +#include +#elif defined(__CK803__) || defined(__E803__) || defined(__E803T__) || defined(__S803__) || defined(__S803T__) +#include +#elif defined(__CK805__) || defined(__I805__) || defined(__I805F__) +#include +#elif defined(__CK610__) +#include +#elif defined(__CK810__) || defined(__C810__) || defined(__C810T__) || defined(__C810V__) || defined(__C810VT__) +#include +#elif defined(__CK807__) || defined(__C807__) || defined(__C807F__) || defined(__C807FV__) || defined(__R807__) +#include +#endif +#include + +#elif defined(__riscv) + +#if CONFIG_CPU_XUANTIE_E906 || CONFIG_CPU_XUANTIE_E906F || CONFIG_CPU_XUANTIE_E906FD || CONFIG_CPU_XUANTIE_E906P || CONFIG_CPU_XUANTIE_E906FP || CONFIG_CPU_XUANTIE_E906FDP \ + || CONFIG_CPU_XUANTIE_E907 || CONFIG_CPU_XUANTIE_E907F || CONFIG_CPU_XUANTIE_E907FD || CONFIG_CPU_XUANTIE_E907P || CONFIG_CPU_XUANTIE_E907FP || CONFIG_CPU_XUANTIE_E907FDP \ + || CONFIG_CPU_XUANTIE_E902 || CONFIG_CPU_XUANTIE_E902M || CONFIG_CPU_XUANTIE_E902T || CONFIG_CPU_XUANTIE_E902MT +#include +#include +#else +#include +#include +#endif /* end exx */ + +#endif /* __csky__ */ + +#ifdef __arm__ +#include +#endif + +#ifdef __ARM_ARCH_ISA_A64 +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_CPU_XUANTIE_E9XX || CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV +#if CONFIG_SMP +#error "This CPU does not support SMP." +#endif +#endif + +__STATIC_INLINE const char* csi_get_cpu_name() +{ +#if CONFIG_CPU_XUANTIE_C906 + return "c906"; +#elif CONFIG_CPU_XUANTIE_C906FD + return "c906fd"; +#elif CONFIG_CPU_XUANTIE_C906FDV + return "c906fdv"; +#elif CONFIG_CPU_XUANTIE_C907 + return "c907"; +#elif CONFIG_CPU_XUANTIE_C907FD + return "c907fd"; +#elif CONFIG_CPU_XUANTIE_C907FDV + return "c907fdv"; +#elif CONFIG_CPU_XUANTIE_C907FDVM + return "c907fdvm"; +#elif CONFIG_CPU_XUANTIE_C907_RV32 + return "c907-rv32"; +#elif CONFIG_CPU_XUANTIE_C907FD_RV32 + return "c907fd-rv32"; +#elif CONFIG_CPU_XUANTIE_C907FDV_RV32 + return "c907fdv-rv32"; +#elif CONFIG_CPU_XUANTIE_C907FDVM_RV32 + return "c907fdvm-rv32"; +#elif CONFIG_CPU_XUANTIE_C908 + return "c908"; +#elif CONFIG_CPU_XUANTIE_C908V + return "c908v"; +#elif CONFIG_CPU_XUANTIE_C908I + return "c908i"; +#elif CONFIG_CPU_XUANTIE_C910V2 + return "c910v2"; +#elif CONFIG_CPU_XUANTIE_C910V3 + return "c910v3"; +#elif CONFIG_CPU_XUANTIE_C910V3_CP + return "c910v3-cp"; +#elif CONFIG_CPU_XUANTIE_C920V2 + return "c920v2"; +#elif CONFIG_CPU_XUANTIE_C920V3 + return "c920v3"; +#elif CONFIG_CPU_XUANTIE_C920V3_CP + return "c920v3-cp"; +#elif CONFIG_CPU_XUANTIE_R910 + return "r910"; +#elif CONFIG_CPU_XUANTIE_R920 + return "r920"; +#elif CONFIG_CPU_XUANTIE_R908 + return "r908"; +#elif CONFIG_CPU_XUANTIE_R908FD + return "r908fd"; +#elif CONFIG_CPU_XUANTIE_R908FDV + return "r908fdv"; +#elif CONFIG_CPU_XUANTIE_R908_CP + return "r908-cp"; +#elif CONFIG_CPU_XUANTIE_R908FD_CP + return "r908fd-cp"; +#elif CONFIG_CPU_XUANTIE_R908FDV_CP + return "r908fdv-cp"; + +#elif CONFIG_CPU_XUANTIE_E902 + return "e902"; +#elif CONFIG_CPU_XUANTIE_E902M + return "e902m"; +#elif CONFIG_CPU_XUANTIE_E902T + return "e902t"; +#elif CONFIG_CPU_XUANTIE_E902MT + return "e902mt"; +#elif CONFIG_CPU_XUANTIE_E906 + return "e906"; +#elif CONFIG_CPU_XUANTIE_E906F + return "e906f"; +#elif CONFIG_CPU_XUANTIE_E906FD + return "e906fd"; +#elif CONFIG_CPU_XUANTIE_E906P + return "e906p"; +#elif CONFIG_CPU_XUANTIE_E906FP + return "e906fp"; +#elif CONFIG_CPU_XUANTIE_E906FDP + return "e906fdp"; +#elif CONFIG_CPU_XUANTIE_E907 + return "e907"; +#elif CONFIG_CPU_XUANTIE_E907F + return "e907f"; +#elif CONFIG_CPU_XUANTIE_E907FD + return "e907fd"; +#elif CONFIG_CPU_XUANTIE_E907P + return "e907p"; +#elif CONFIG_CPU_XUANTIE_E907FP + return "e907fp"; +#elif CONFIG_CPU_XUANTIE_E907FDP + return "e907fdp"; +#else + return "unknown"; +#endif +} + + +#ifdef __cplusplus +} +#endif + +#endif /* _CORE_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/adc.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/adc.h new file mode 100644 index 00000000000..609fb851d59 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/adc.h @@ -0,0 +1,212 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/adc.h + * @brief Header File for ADC Driver + * @version V1.0 + * @date 08. Apr 2020 + * @model adc + ******************************************************************************/ + +#ifndef _DRV_ADC_H_ +#define _DRV_ADC_H_ + +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****** ADC Event *****/ +typedef enum { + ADC_EVENT_CONVERT_COMPLETE = 0, ///< All data convert completed + ADC_EVENT_CONVERT_HALF_DONE, ///< Convert half done + ADC_EVENT_ERROR ///< All errors including but not limited to what converted data has not been read before the new conversion result is load to the data register +} csi_adc_event_t; + +typedef struct csi_adc csi_adc_t; +struct csi_adc { + csi_dev_t dev; ///< Hw-device info + void (*callback)(csi_adc_t *adc, csi_adc_event_t event, void *arg); ///< User callback ,signaled by driver event + void *arg; ///< User private param ,passed to user callback + uint32_t *data; ///< Data buf + uint32_t num; ///< Data size by word + csi_dma_ch_t *dma; ///< Dma channel handle + csi_error_t (*start)(csi_adc_t *adc); ///< Start function + csi_error_t (*stop)(csi_adc_t *adc); ///< Stop function + csi_state_t state; ///< ADC current state + void *priv; +}; + +/** + \brief Initialize adc Interface. Initialize the resources needed for the adc interface + \param[in] adc ADC handle to operate + \param[in] idx ADC controller index + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_init(csi_adc_t *adc, uint32_t idx); + +/** + \brief De-initialize adc Interface. stops operation and releases the software resources used by the interface + \param[in] handle ADC handle to operate + \return None +*/ +void csi_adc_uninit(csi_adc_t *adc); + +/** + \brief Set adc receive buffer + \param[in] adc ADC handle to operate + \param[in] num The receive data length by word. + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_set_buffer(csi_adc_t *adc, uint32_t *data, uint32_t num); + +/** + \brief Start adc + \param[in] handle ADC handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_start(csi_adc_t *adc); + +/** + \brief Enable dma or interrupt, and start adc conversion + \param[in] handle ADC handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_start_async(csi_adc_t *adc); + +/** + \brief Stop adc + \param[in] handle ADC handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_stop(csi_adc_t *adc); + +/** + \brief Disable dma or interrupt, and stop adc conversion + \param[in] handle ADC handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_stop_async(csi_adc_t *adc); + +/** + \brief ADC channel enable + \param[in] adc ADC handle to operate + \param[in] ch_id ADC channel id + \param[in] is_enable true->enable, false->disable + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_channel_enable(csi_adc_t *adc, uint8_t ch_id, bool is_enable); + +/** + \brief Set the ADC sampling time for the selected channel + \param[in] adc ADC handle to operate + \param[in] ch_id ADC channel id + \param[in] clock_num Channel sampling clock number + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_channel_sampling_time(csi_adc_t *adc, uint8_t ch_id, uint16_t clock_num); + +/** + \brief Set the ADC controller sampling time + \param[in] adc ADC handle to operate + \param[in] clock_num ADC controller sampling clock number + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_sampling_time(csi_adc_t *adc, uint16_t clock_num); + +/** + \brief Enable the continue mode of ADC + \param[in] adc ADC handle to operate + \param[in] is_enable true->enable, false->disable + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_continue_mode(csi_adc_t *adc, bool is_enable); + +/** + \brief Set ADC frequence division + \param[in] adc ADC handle to operate + \param[in] div The division of frequence + \return The actual config frequency +*/ +uint32_t csi_adc_freq_div(csi_adc_t *adc, uint32_t div); + +/** + \brief Receiving data from ADC receiver + \param[in] handle ADC handle to operate + \return If read successful, this function shall return the result of convert value + otherwise, the function shall return error code +*/ +int32_t csi_adc_read(csi_adc_t *adc); + +/** + \brief Get ADC state + \param[in] adc ADC handle to operate + \param[in] state ADC state + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_get_state(csi_adc_t *adc, csi_state_t *state); + +/** + \brief Attach the callback handler to adc + \param[in] adc Operate handle + \param[in] callback Callback function + \param[in] arg User can define it by himself as callback's param + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_attach_callback(csi_adc_t *adc, void *callback, void *arg); + +/** + \brief Detach the callback handler + \param[in] adc Operate handle + \return None +*/ +void csi_adc_detach_callback(csi_adc_t *adc); + +/** + \brief Link DMA channel to adc device + \param[in] adc ADC handle to operate + \param[in] dma The DMA channel handle for send, when it is NULL means to unlink the channel + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_link_dma(csi_adc_t *adc, csi_dma_ch_t *dma); + +/** + \brief Enable adc low power mode + \param[in] adc ADC handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_adc_enable_pm(csi_adc_t *adc); + +/** + \brief Disable adc low power mode + \param[in] adc ADC handle to operate + \return None +*/ +void csi_adc_disable_pm(csi_adc_t *adc); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_ADC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/aes.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/aes.h new file mode 100644 index 00000000000..4a56bc65357 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/aes.h @@ -0,0 +1,309 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/aes.h + * @brief Header File for AES Driver + * @version V1.0 + * @date 9. Oct 2020 + * @model aes + ******************************************************************************/ + +#ifndef _DRV_AES_H_ +#define _DRV_AES_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*----- Encrypt & Decrypt: Config key length -----*/ +typedef enum { + AES_KEY_LEN_BITS_128 = 0, /* 128 Data bits */ + AES_KEY_LEN_BITS_192, /* 192 Data bits */ + AES_KEY_LEN_BITS_256 /* 256 Data bits */ +} csi_aes_key_bits_t; + +/** +\brief AES Ctrl Block +*/ +typedef struct { + csi_dev_t dev; + void *priv; +} csi_aes_t; + +/** + \brief Initialize AES interface. Initializes the resources needed for the AES interface + \param[in] aes Handle to operate + \param[in] idx Device id + \return Error code \ref csi_error_t +*/ +csi_error_t csi_aes_init(csi_aes_t *aes, uint32_t idx); + +/** + \brief De-initialize AES interface. Stops operation and releases the software resources used by the interface + \param[in] aes Dandle to operate + \return None +*/ +void csi_aes_uninit(csi_aes_t *aes); + +/** + \brief Set encrypt key + \param[in] aes Handle to operate + \param[in] key Pointer to the key buf + \param[in] key_len Pointer to \ref csi_aes_key_bits_t + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_set_encrypt_key(csi_aes_t *aes, void *key, csi_aes_key_bits_t key_len); + +/** + \brief Set decrypt key + \param[in] aes Handle to operate + \param[in] key Pointer to the key buf + \param[in] key_len Pointer to \ref csi_aes_key_bits_t + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_set_decrypt_key(csi_aes_t *aes, void *key, csi_aes_key_bits_t key_len); +/** + \brief Set encrypt key2. This API is used for the algorithm which has two keys, + such as xts, used for the key of tweak + \param[in] aes Handle to operate + \param[in] key Pointer to the key buf + \param[in] key_len Pointer to \ref csi_aes_key_bits_t + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_set_encrypt_key2(csi_aes_t *aes, void *key, csi_aes_key_bits_t key_len); + +/** + \brief Set decrypt key2. This API is used for the algorithm which has two keys, + such as xts, used for the key of tweak + \param[in] aes Handle to operate + \param[in] key Pointer to the key buf + \param[in] key_len Pointer to \ref csi_aes_key_bits_t + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_set_decrypt_key2(csi_aes_t *aes, void *key, csi_aes_key_bits_t key_len); + +/** + \brief AES ecb encrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_ecb_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size); + +/** + \brief AES ecb decrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_ecb_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size); + +/** + \brief AES cbc encrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_cbc_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv); + +/** + \brief AES cbc decrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_cbc_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv); + +/** + \brief AES cfb1 encrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_cfb1_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv); + +/** + \brief AES cfb1 decrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_cfb1_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv); + +/** + \brief AES cfb8 encrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_cfb8_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv); + +/** + \brief AES cfb8 decrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_aes_cfb8_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv); + +/** + \brief AES cfb128 decrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \param[out] num The number of the 128-bit block we have used + \return Error code \ref csi_error_t +*/ +csi_error_t csi_aes_cfb128_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv, uint32_t *num); + +/** + \brief AES cfb128 encrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \param[out] num The number of the 128-bit block we have used + \return Error code \ref csi_error_t +*/ +csi_error_t csi_aes_cfb128_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv, uint32_t *num); + +/** + \brief AES ofb encrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \param[out] num The number of the 128-bit block we have used + \return Error code \ref csi_error_t +*/ +csi_error_t csi_aes_ofb_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv, uint32_t *num); + +/** + \brief AES ofb decrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \param[out] num The number of the 128-bit block we have used + \return Error code \ref csi_error_t +*/ +csi_error_t csi_aes_ofb_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv, uint32_t *num); + +/** + \brief AES ctr encrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref csi_error_t +*/ +csi_error_t csi_aes_ctr_encrypt(csi_aes_t *aes, void *in,void *out, uint32_t size, void *iv); + +/** + \brief AES ctr decrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vecotr + \return Error code \ref csi_error_t +*/ +csi_error_t csi_aes_ctr_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv); + +/** + \brief AES cts encrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref csi_error_t +*/ +csi_error_t csi_aes_cts_encrypt(csi_aes_t *aes, void *in,void *out, uint32_t size, void *iv); + +/** + \brief AES cts decrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vecotr + \return Error code \ref csi_error_t +*/ +csi_error_t csi_aes_cts_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv); + + +/** + \brief AES xts encrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref csi_error_t +*/ +csi_error_t csi_aes_xts_encrypt(csi_aes_t *aes, void *in,void *out, uint32_t size, void *iv); + +/** + \brief AES xts decrypt + \param[in] aes Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vecotr + \return Error code \ref csi_error_t +*/ +csi_error_t csi_aes_xts_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_AES_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/baud_calc.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/baud_calc.h new file mode 100644 index 00000000000..b39e0c02a2a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/baud_calc.h @@ -0,0 +1,58 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/baud_calc.h + * @brief Header File for the PWM capture uart bandrate Driver + * @version V1.0 + * @date 9. Oct 2020 + * @model baud_calc + ******************************************************************************/ + +#ifndef _DRV_BAUD_CALC_H_ +#define _DRV_BAUD_CALC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + \brief Baud rate calculation(Algorithm level) + \param[in] idx PWM idx + \param[in] channel Channel num + \return Error code(-1) or Baudare value +*/ +int drv_calc_baud_adjust(uint32_t idx, uint32_t channel); + +/** + \brief Baud rate calculation(Capture level) + \param[in] idx PWM idx + \param[in] channel Channel num + \return Error code(-1) or Baudare value +*/ +int drv_calc_baud_original(uint32_t idx, uint32_t channel); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_BAUD_CALC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/clk.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/clk.h new file mode 100644 index 00000000000..9e9ee03ed7c --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/clk.h @@ -0,0 +1,50 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/clk.h + * @brief Header File for CLK Driver. + * @version V1.0 + * @date 18. Mar 2020 + ******************************************************************************/ + +#ifndef _DRV_CLK_H_ +#define _DRV_CLK_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t module; + uint16_t dev_tag; + uint8_t idx; +} csi_clkmap_t; + +void csi_clk_enable(csi_dev_t *dev); +void csi_clk_disable(csi_dev_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_CLK_H_ */ + diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/codec.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/codec.h new file mode 100644 index 00000000000..d96a40b03a9 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/codec.h @@ -0,0 +1,450 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/codec.h + * @brief head file for codec + * @version V1.0 + * @date 17. Mar 2020 + * @model codec + ******************************************************************************/ +#ifndef _DRV_CODEC_H_ +#define _DRV_CODEC_H_ + +#include +#include +#include +#include +#include "drv/ringbuf.h" + +typedef enum { + CODEC_EVENT_PERIOD_READ_COMPLETE = 0U, ///< A peroid data read completed + CODEC_EVENT_PERIOD_WRITE_COMPLETE = 1U, ///< A peroid data write completed + CODEC_EVENT_WRITE_BUFFER_EMPTY = 2U, ///< Fifo is empty + CODEC_EVENT_READ_BUFFER_FULL = 3U, ///< Fifo is full + CODEC_EVENT_ERROR_OVERFLOW = 4U, ///< Fifo overflow error + CODEC_EVENT_ERROR_UNDERFLOW = 5U, ///< Fifo underflow error + CODEC_EVENT_ERROR = 6U, ///< The device has a hardware error +} csi_codec_event_t; + +struct csi_codec; +typedef struct csi_codec csi_codec_t; +typedef struct csi_codec_output csi_codec_output_t; +struct csi_codec_output { + csi_codec_t *codec; + uint32_t ch_idx; ///< Codec output channel idx + void (*callback)(csi_codec_output_t *output, csi_codec_event_t event, void *arg); + void *arg; + csi_ringbuf_t *ring_buf; ///< The csi_ringbuf used to save audio data + uint32_t period; ///< When the period data is sent, the callback function will be called + uint32_t sound_channel_num; ///< Number of sound channel + csi_dma_ch_t *dma; ///< Dma channel handle + csi_state_t state; ///< Codec output channel current state + void *priv; + struct csi_codec_output *next; +}; + +typedef struct csi_codec_input csi_codec_input_t; +struct csi_codec_input { + csi_codec_t *codec; + uint32_t ch_idx; ///< Codec input channel idx + void (*callback)(csi_codec_input_t *input, csi_codec_event_t event, void *arg); + void *arg; + csi_ringbuf_t *ring_buf; ///< The csi_ringbuf used to save audio data + uint32_t period; ///< When the period data is received, the callback function will be called + uint32_t sound_channel_num; ///< Number of sound channel + csi_dma_ch_t *dma; ///< Codec input channel current state + csi_state_t state; ///< Dma channel handle + void *priv; + struct csi_codec_input *next; +}; + +struct csi_codec { + csi_dev_t dev; ///< Codec hw-device info + csi_codec_output_t *output_chs; ///< Codec output channel operate handle + csi_codec_input_t *input_chs; ///< Codec input channel operate handle + void *priv; ///< User private param passed to user callback +}; + +typedef enum { + CODEC_OUTPUT_SINGLE_ENDED, ///< Single-ended output + CODEC_OUTPUT_DIFFERENCE, ///< Differential output +} csi_codec_output_mode_t; + +typedef enum { + CODEC_INPUT_SINGLE_ENDED, ///< Single-ended input + CODEC_INPUT_DIFFERENCE, ///< Differential input +} csi_codec_input_mode_t; + +typedef struct { + uint32_t sample_rate; ///< Input data sample rate + uint32_t bit_width; ///< Input data sample width + csi_codec_input_mode_t mode; ///< Input work mode + uint8_t *buffer; ///< The buffer used to save audio data + uint32_t buffer_size; ///< Input buffer size + uint32_t period; ///< When a peroid data is reached,the callback function is called + uint32_t sound_channel_num; ///< Number of soundtrack per channel +} csi_codec_input_config_t; + +typedef struct { + uint32_t sample_rate; ///< Output data sample rate + uint32_t bit_width; ///< Onput data sample width + csi_codec_output_mode_t mode; ///< Onput work mode + uint8_t *buffer; ///< The buffer used to save audio data + uint32_t buffer_size; ///< Output buffer size + uint32_t period; ///< When a peroid data is reached,the callback function is called + uint32_t sound_channel_num; ///< Number of soundchannel per channel +} csi_codec_output_config_t; + +/** + \brief Init the codec according to the specified + \param[in] codec Codec handle to operate + \param[in] idx Codec interface idx + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_init(csi_codec_t *codec, uint32_t idx); + +/** + \brief Codec uninit + \param[in] codec Codec handle to operate + \return None +*/ +void csi_codec_uninit(csi_codec_t *codec); + +/** + \brief Open a codec output channel + \param[in] codec Codec handle to operate + \param[in] ch Codec output channel handle + \param[in] ch_idx Codec output channel idx + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_open(csi_codec_t *codec, csi_codec_output_t *ch, uint32_t ch_idx); + +/** + \brief Config codec output channel + \param[in] ch Codec output channel handle + \param[in] config Codec channel param. \ref csi_codec_output_config_t + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_config(csi_codec_output_t *ch, csi_codec_output_config_t *config); + +/** + \brief Attach the callback handler to codec output + \param[in] ch Codec output channel handle + \param[in] cb Callback function + \param[in] arg User private param + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_attach_callback(csi_codec_output_t *ch, void *callback, void *arg); + +/** + \brief Detach the callback handler + \param[in] ch Codec output channel handle + \return None +*/ +void csi_codec_output_detach_callback(csi_codec_output_t *ch); + +/** + \brief Close a codec output channel + \param[in] ch Codec output channel handle + \return error code \ref csi_error_t +*/ +void csi_codec_output_close(csi_codec_output_t *ch); + +/** + \brief Link DMA channel to codec output channel + \param[in] ch Codec output channel handle + \param[in] dma The codec output DMA channel handle, when it is NULL means to unlink the channel + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_link_dma(csi_codec_output_t *ch, csi_dma_ch_t *dma); + +/** + \brief Send an amount of data to buffer in blocking mode + \param[in] ch The codec output channel + \param[in] data Pointer to send data buffer + \param[in] size Send data size + \return the num of data witch is send successful +*/ +uint32_t csi_codec_output_write(csi_codec_output_t *ch, const void *data, uint32_t size); + +/** + \brief Send data to the buffer with asynchronous sending + The data is first written to the buffer and then output through the codec interface + This function does not block, and the return value is the number + Of data that was successfully written to the buffer + \param[in] ch The codec output channel + \param[in] data Pointer to send data buffer + \param[in] size Send data size + \return The data size that send to buffer +*/ +uint32_t csi_codec_output_write_async(csi_codec_output_t *ch, const void *data, uint32_t size); + +/** + \brief Start sending data from the buffer + \param[in] ch Codec output channel handle + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_start(csi_codec_output_t *ch); + +/** + \brief Stop sending data from the buffer + \param[in] ch Codec output channel handle + \return None +*/ +void csi_codec_output_stop(csi_codec_output_t *ch); + +/** + \brief Pause sending data from the buffer + \param[in] ch Codec output channel handle + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_pause(csi_codec_output_t *ch); + +/** + \brief Resume sending data from the buffer + \param[in] ch Codec output channel handle + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_resume(csi_codec_output_t *ch); + +/** + \brief Get output-buffer free space + \param[in] ch Codec output channel handle + \return Buffer free space (bytes) +*/ +uint32_t csi_codec_output_buffer_avail(csi_codec_output_t *ch); + +/** + \brief Get used space of output-buffer + \param[in] ch Codec output channel handle + \return Buffer free space (bytes) +*/ +uint32_t csi_codec_output_buffer_remain(csi_codec_output_t *ch); + +/** + \brief Reset the buf, discard all data in the buffer + \param[in] ch Codec output channel handle + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_buffer_reset(csi_codec_output_t *ch); + +/** + \brief Mute codec ouput channel + \param[in] ch Codec output channel handle + \param[in] en True enable codec mute. false disable codec mute + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_mute(csi_codec_output_t *ch, bool enable); + +/** + \brief Set codec ouput channel digital gain + \param[in] ch Codec output channel handle + \param[in] val Gain val + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_digital_gain(csi_codec_output_t *ch, uint32_t val); + +/** + \brief Set codec ouput channel analog gain + \param[in] ch Codec output channel handle + \param[in] val Gain val + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_analog_gain(csi_codec_output_t *ch, uint32_t val); + +/** + \brief Set codec ouput channel mix gain + \param[in] ch Codec output channel handle + \param[in] val Gain val + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_output_mix_gain(csi_codec_output_t *ch, uint32_t val); + +/** + \brief Get codec output channel state + \param[in] ch Codec output channel handle + \param[out] state Channel state. \ref csi_state_t + \return channel state +*/ +csi_error_t csi_codec_output_get_state(csi_codec_output_t *ch, csi_state_t *state); + +/** + \brief Open a codec input channel + \param[in] codec Codec handle to operate + \param[in] ch Codec input channel handle + \param[in] ch_idx Codec input channel idx + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_input_open(csi_codec_t *codec, csi_codec_input_t *ch, uint32_t ch_idx); + +/** + \brief Config codec input channel + \param[in] ch Codec input channel handle + \param[in] config Codec channel prarm. \ref csi_codec_input_config_t + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_input_config(csi_codec_input_t *ch, csi_codec_input_config_t *config); + +/** + \brief Attach the callback handler to codec output + \param[in] ch Codec input channel handle + \param[in] cb Callback function + \param[in] arg User private param for event callback + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_input_attach_callback(csi_codec_input_t *ch, void *callback, void *arg); + +/** + \brief Detach the callback handler + \param[in] ch Codec input channel handle + \return None +*/ +void csi_codec_input_detach_callback(csi_codec_input_t *ch); + +/** + \brief Close a codec input channel + \param[in] ch Codec input channel handle + \return None +*/ +void csi_codec_input_close(csi_codec_input_t *ch); + +/** + \brief Link DMA channel to codec input channel + \param[in] ch Codec input channel handle + \param[in] dma The codec input DMA channel handle, when it is NULL means to unlink the channel + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_input_link_dma(csi_codec_input_t *ch, csi_dma_ch_t *dma); + +/** + \brief Read an amount of data in blocking mode + \param[in] ch Codec input channel handle + \param[in] data Pointer to receive data buffer + \param[in] size Receive data size + \return The size of data read successfully +*/ +uint32_t csi_codec_input_read(csi_codec_input_t *ch, void *data, uint32_t size); + +/** + \brief Read data from the buffer + using asynchronous receive + this function read data from the buffer, returns the number of successful receive + and returns 0 if there is no data in the buffer + \param[in] ch Codec input channel handle + \param[in] data Pointer to receive data buffer + \param[in] size Receive data size + \return The size of data read successfully +*/ +uint32_t csi_codec_input_read_async(csi_codec_input_t *ch, void *data, uint32_t size); + +/** + \brief Start receive data to the buffer + \param[in] ch Codec input channel handle + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_input_start(csi_codec_input_t *ch); + +/** + \brief Stop receive data + \param[in] ch Codec input channel handle + \return None +*/ +void csi_codec_input_stop(csi_codec_input_t *ch); + +/** + \brief Reset the buf, discard all data in the buffer + \param[in] ch Codec input channel handle + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_input_buffer_reset(csi_codec_input_t *ch); + +/** + \brief Get input-buffer free space + \param[in] ch Codec input channel handle + \return Buffer free space (bytes) +*/ +uint32_t csi_codec_input_buffer_avail(csi_codec_input_t *ch); + +/** + \brief Get used space of input-buffer + \param[in] ch Codec input channel handle + \return Buffer free space (bytes) +*/ +uint32_t csi_codec_input_buffer_remain(csi_codec_input_t *ch); + +/** + \brief Mute codec input channel + \param[in] ch Codec input channel handle + \param[in] en True enable codec mute. false disable codec mute + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_input_mute(csi_codec_input_t *ch, bool en); + +/** + \brief Set codec input channel digital gain + \param[in] ch Codec input channel handle + \param[in] val Gain val + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_input_digital_gain(csi_codec_input_t *ch, uint32_t val); + +/** + \brief Set codec input channel analog gain + \param[in] ch Codec input channel handle + \param[in] val Gain val + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_input_analog_gain(csi_codec_input_t *ch, uint32_t val); + +/** + \brief Set codec input channel mix gain + \param[in] ch Codec input channel handle + \param[in] val Gain val + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_input_mix_gain(csi_codec_input_t *ch, uint32_t val); + +/** + \brief Get codec input channel state + \param[in] ch Codec input channel handle + \param[out] state Channel state + \return Channel state +*/ +csi_error_t csi_codec_input_get_state(csi_codec_input_t *ch, csi_state_t *state); + +/** + \brief Enable codec power manage + \param[in] codec Codec handle to operate + \return error code \ref csi_error_t +*/ +csi_error_t csi_codec_enable_pm(csi_codec_t *codec); + +/** + \brief Disable codec power manage + \param[in] codec Codec handle to operate + \return None +*/ +void csi_codec_disable_pm(csi_codec_t *codec); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_CODEC_H_ */ + diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/common.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/common.h new file mode 100644 index 00000000000..b3223f9e14a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/common.h @@ -0,0 +1,151 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/common.h + * @brief Header File for Common Driver + * @version V1.0 + * @date 31. March 2020 + * @model common + ******************************************************************************/ + +#ifndef _DRV_COMMON_H_ +#define _DRV_COMMON_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_DEBUG_MODE +#define CSI_ASSERT(expr) \ + do { \ + if ((long)expr == (long)NULL) { \ + printf("PROGRAM ASSERT\n"); \ + while(1); \ + } \ + } while(0); +#else +#define CSI_ASSERT(expr) ((void)0U) +#endif + +#ifndef CONFIG_PARAM_NOT_CHECK +#define CSI_PARAM_CHK(para, err) \ + do \ + { \ + if ((unsigned long)para == (unsigned long)NULL) \ + { \ + return (err); \ + } \ + } while (0) + +#define CSI_PARAM_CHK_NORETVAL(para) \ + do \ + { \ + if ((unsigned long)para == (unsigned long)NULL) \ + { \ + return; \ + } \ + } while (0) +#else +#define CSI_PARAM_CHK(para, err) +#define CSI_PARAM_CHK_NORETVAL(para) +#endif + +typedef enum { + CSI_OK = 0, + CSI_ERROR = -1, + CSI_BUSY = -2, + CSI_TIMEOUT = -3, + CSI_UNSUPPORTED = -4 +} csi_error_t; + +typedef struct { + uint8_t readable; + uint8_t writeable; + uint8_t error; +} csi_state_t; + +typedef struct csi_dev csi_dev_t; + +#ifdef CONFIG_PM +typedef enum { + PM_DEV_SUSPEND, + PM_DEV_RESUME, +} csi_pm_dev_action_t; + +typedef enum { + PM_MODE_RUN = 0, ///< Running mode + PM_MODE_SLEEP_1, ///< Sleep LV1 mode + PM_MODE_SLEEP_2, ///< Sleep LV2 mode + PM_MODE_DEEP_SLEEP_1, ///< Deep sleep LV1 mode + PM_MODE_DEEP_SLEEP_2, ///< Deep sleep LV2 mode +} csi_pm_mode_t; + +typedef struct { + slist_t next; + csi_error_t (*pm_action)(csi_dev_t *dev, csi_pm_dev_action_t action); + uint32_t *reten_mem; + uint32_t size; +} csi_pm_dev_t; +#include +#endif + +struct csi_dev { + unsigned long reg_base; + uint16_t irq_num; + uint16_t idx; + uint16_t dev_tag; + void (*irq_handler)(void *); + void (*irq_handler2)(uint32_t irqn, void *arg); + void *arg; +#ifdef CONFIG_PM + csi_pm_dev_t pm_dev; +#endif +}; + +#define HANDLE_REG_BASE(handle) (handle->dev.reg_base) +#define HANDLE_IRQ_NUM(handle) (handle->dev.irq_num) +#define HANDLE_DEV_IDX(handle) (handle->dev.idx) +#define HANDLE_IRQ_HANDLER(handle) (handle->dev.irq_handler) + +typedef struct { + unsigned long reg_base; + uint16_t irq_num; + uint16_t idx; + uint16_t dev_tag; +} csi_perip_info_t; + +csi_error_t target_get(csi_dev_tag_t dev_tag, uint32_t idx, csi_dev_t *dev); +csi_error_t target_get_optimal_dma_channel(void *dma_list, uint32_t ctrl_num, csi_dev_t *parent_dev, void *ch_info); +void mdelay(uint32_t ms); +void udelay(uint32_t us); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_COMMON_H_ */ + diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/crc.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/crc.h new file mode 100644 index 00000000000..2fbd43db1a3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/crc.h @@ -0,0 +1,136 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file crc.h + * @brief Header File for CRC Driver + * @version V1.0 + * @date 02. June 2020 + * @model crc + ******************************************************************************/ + +#ifndef _DRV_CRC_H_ +#define _DRV_CRC_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Compute the CRC-7 checksum of a buffer. + * + * See JESD84-A441. Used by the MMC protocol. Uses 0x09 as the + * polynomial with no reflection. The CRC is left + * justified, so bit 7 of the result is bit 6 of the CRC. + * init = 0; poly = 0x09 refin = 0 refout = 0 xorout = 0 + * \param[in] crc Crc init value or crc immediate result + * \param[in] data Data buf to be calculate + * \param[in] size Data size + * + * \return The computed CRC7 value + */ +uint8_t csi_crc7_be(uint8_t crc, uint8_t *data, uint32_t size); + +/** + * \brief Compute the CRC-8 checksum of a buffer. + * init = 0 or 0xff; poly = 0x07 refin = 0 refout = 0 xorout = 0 + * \param[in] crc Crc init value or crc immediate result + * \param[in] data Data buf to be calculate + * \param[in] size Data size + * \return The computed CRC8 value + */ +uint8_t csi_crc8(uint8_t crc, uint8_t *data, size_t size); + +/** + * \brief Compute the CRC-8 checksum of a buffer. + * init = 0; poly = 0x31 refin = 1 refout = 1 xorout = 0 + * \param[in] crc Crc init value or crc immediate result + * \param[in] data Data buf to be calculate + * \param[in] size Data size + * \return The computed CRC8 value + */ +uint8_t csi_crc8_maxim(uint8_t crc, uint8_t *data, size_t size); + +/** + * \brief Compute the CRC-16 checksum of a buffer. + * init = 0 or 0xffff; poly = 0x8005 refin = 1 refout = 1 xorout = 0 + * \param[in] crc Crc init value or crc immediate result + * \param[in] data Data buf to be calculate + * \param[in] size Data size + * \return The computed CRC16 without xorout + */ +uint16_t csi_crc16(uint16_t crc, uint8_t *data, uint32_t size); + +/** + * \brief Compute the CRC-16 checksum of a buffer. + * init = 0; poly = 0x1021 refin = 1 refout = 1 xorout = 0 + * \param[in] crc Crc init value or crc immediate result + * \param[in] data Data buf to be calculate + * \param[in] size Data size + * \return The computed CRC16 without xorout + */ +uint16_t csi_crc16_ccitt(uint16_t crc, uint8_t *data, uint32_t size); + +/** + * \brief Compute the CRC-16 checksum of a buffer. + * init = 0; poly = 0x3d65 refin = 1 refout = 1 xorout = 0xffff + * \param[in] init_value Crc init value + * \param[in] data Data buf to be calculate + * \param[in] size Data size + * \return The computed CRC16 with xorout + */ +uint16_t csi_crc16_dnp(uint16_t init_value, uint8_t *data, uint32_t size); + +/** + * \brief Compute the CRC-16 checksum of a buffer. + * init = 0; poly = 0x1021 refin = 0 refout = 0 xorout = 0 + * \param[in] crc Crc init value or crc immediate result + * \param[in] data Data buf to be calculate + * \param[in] size Data size + * \return The computed CRC16 without xorout + */ +uint16_t csi_crc16_itu(uint16_t crc, uint8_t *data, uint32_t size); + +/** + * \brief Compute the CRC-32 checksum of a buffer.Little-endian by bit. + * init = 0; poly = 0xEDB88320 refin = 0 refout = 0 xorout = 0 + * \param[in] crc Crc init value or crc immediate result + * \param[in] data Data buf to be calculate + * \param[in] size Data size + * \return The computed CRC32 without xorout + */ +uint32_t csi_crc32_le(uint32_t crc, uint8_t *data, uint32_t size); + +/** + * \brief Compute the CRC-32 checksum of a buffer.Big-endian by bit. + * init = 0; poly = 0x04C11DB7 refin = 0 refout = 0 xorout = 0 + * \param[in] crc Crc init value or crc immediate result + * \param[in] data Data buf to be calculate + * \param[in] size Data size + * \return The computed CRC32 without xorout + */ +uint32_t csi_crc32_be(uint32_t crc, uint8_t *data, uint32_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_CRC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/des.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/des.h new file mode 100644 index 00000000000..2b0540eaf29 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/des.h @@ -0,0 +1,174 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/des.h + * @brief Header File for DES Driver + * @version V1.0 + * @date 24. Oct 2022 + * @model des + ******************************************************************************/ + +#ifndef _DRV_DES_H_ +#define _DRV_DES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** +\brief DES key-len-bits type +*/ +typedef enum { + DES_KEY_LEN_BITS_64 = 0, /*64 Data bits*/ + DES_KEY_LEN_BITS_128, /*128 Data bits*/ + DES_KEY_LEN_BITS_192, /*192 Data bits*/ +} csi_des_key_bits_t; + +/** +\brief DES Ctrl Block +*/ +typedef struct { + csi_dev_t dev; + void *priv; +} csi_des_t; + +/** + \brief Initialize DES interface. Initializes the resources needed for the DES interface + \param[in] des Handle to operate + \param[in] idx Device id + \return Error code \ref csi_error_t +*/ +csi_error_t csi_des_init(csi_des_t *des, uint32_t idx); + +/** + \brief De-initialize DES interface. Stops operation and releases the software resources used by the interface + \param[in] des Dandle to operate + \return None +*/ +void csi_des_uninit(csi_des_t *des); + +/** + \brief Set encrypt key + \param[in] des Handle to operate + \param[in] key Pointer to the key buf + \param[in] key_len Pointer to \ref csi_des_key_bits_t + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_des_set_encrypt_key(csi_des_t *des, void *key, csi_des_key_bits_t key_len); + +/** + \brief Set decrypt key + \param[in] des Handle to operate + \param[in] key Pointer to the key buf + \param[in] key_len Pointer to \ref csi_des_key_bits_t + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_des_set_decrypt_key(csi_des_t *des, void *key, csi_des_key_bits_t key_len); + +/** + \brief DES ecb encrypt + \param[in] des Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_des_ecb_encrypt(csi_des_t *des, void *in, void *out, uint32_t size); + +/** + \brief DES ecb decrypt + \param[in] des Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_des_ecb_decrypt(csi_des_t *des, void *in, void *out, uint32_t size); + +/** + \brief DES cbc encrypt + \param[in] des Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_des_cbc_encrypt(csi_des_t *des, void *in, void *out, uint32_t size, void *iv) ; + +/** + \brief DES cbc decrypt + \param[in] des Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_des_cbc_decrypt(csi_des_t *des, void *in, void *out, uint32_t size, void *iv); + +/** + \brief TDES ecb encrypt + \param[in] des Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_tdes_ecb_encrypt(csi_des_t *des, void *in, void *out, uint32_t size); + +/** + \brief TDES ecb decrypt + \param[in] des Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_tdes_ecb_decrypt(csi_des_t *des, void *in, void *out, uint32_t size); + +/** + \brief TDES cbc encrypt + \param[in] des Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_tdes_cbc_encrypt(csi_des_t *des, void *in, void *out, uint32_t size, void *iv) ; + +/** + \brief TDES cbc decrypt + \param[in] des Handle to operate + \param[in] in Pointer to the source data + \param[out] out Pointer to the result data + \param[in] size The source data size + \param[in] iv Init vector + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_tdes_cbc_decrypt(csi_des_t *des, void *in, void *out, uint32_t size, void *iv); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_DES_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/dma.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/dma.h new file mode 100644 index 00000000000..a97b7f80fd7 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/dma.h @@ -0,0 +1,216 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file dma.h + * @brief header file for dma driver + * @version V1.0 + * @date 08. Apr 2020 + * @model dma + ******************************************************************************/ + +#ifndef _DRV_DMA_H_ +#define _DRV_DMA_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****** DMA Event *****/ +typedef enum { + DMA_EVENT_TRANSFER_DONE = 0, ///< transfer complete + DMA_EVENT_TRANSFER_HALF_DONE, ///< transfer half done + DMA_EVENT_TRANSFER_ERROR, ///< transfer error +} csi_dma_event_t; + +typedef enum { + DMA_ADDR_INC = 0, + DMA_ADDR_DEC, + DMA_ADDR_CONSTANT +} csi_dma_addr_inc_t; + +typedef enum { + DMA_DATA_WIDTH_8_BITS = 0, + DMA_DATA_WIDTH_16_BITS, + DMA_DATA_WIDTH_32_BITS, + DMA_DATA_WIDTH_64_BITS, + DMA_DATA_WIDTH_128_BITS, + DMA_DATA_WIDTH_512_BITS +} csi_dma_data_width_t; + +typedef enum { + DMA_MEM2MEM = 0, + DMA_MEM2PERH, + DMA_PERH2MEM, +} csi_dma_trans_dir_t; + +typedef struct { + uint8_t ctrl_idx; + uint8_t ch_idx; +} csi_dma_ch_desc_t; + +typedef struct { + uint16_t dev_tag; + uint8_t ctrl_idx; + const csi_dma_ch_desc_t *ch_list; +} csi_dma_ch_spt_list_t; + +typedef struct { + csi_dma_addr_inc_t src_inc; ///< source address increment + csi_dma_addr_inc_t dst_inc; ///< destination address increment + csi_dma_data_width_t src_tw; ///< source transfer width in byte + csi_dma_data_width_t dst_tw; ///< destination transfer width in byte + csi_dma_trans_dir_t trans_dir; ///< transfer direction + uint16_t handshake; ///< handshake id + uint16_t group_len; ///< group transaction length (unit: bytes) + uint8_t src_reload_en; ///< 1:dma enable src addr auto reload, 0:disable + uint8_t dst_reload_en; ///< 1:dma enable dst addr auto reload, 0:disable + uint8_t half_int_en; ///< 1:dma enable half interrupt, 0: disable + uint8_t lli_src_en; ///< 1:dma enable llp, 0 disable + uint8_t lli_dst_en; ///< 1:dma enable llp, 0 disable +} csi_dma_ch_config_t; + +#ifndef DMA_LLI_SIZE +#define DMA_LLI_SIZE 28 +#endif + +#define DEFINE_DESC_BUF(buf_name, num) uint8_t buf_name[num * DMA_LLI_SIZE] + +typedef struct csi_dma_ch csi_dma_ch_t; + +struct csi_dma_ch { + void *parent; + int8_t ctrl_id; + int8_t ch_id; + void (*callback)(csi_dma_ch_t *dma_ch, csi_dma_event_t event, void *arg); + void *arg; + uint32_t lli_num; //lli buffer len + uint32_t lli_count; //lli data count + int32_t lli_w_p; //write position + int32_t lli_r_p; //read position + void *lli; //lli buffer + uint32_t lli_loop_buf0; //lli loop data + uint32_t lli_loop_buf1; //lli loop data + uint8_t lli_loop[DMA_LLI_SIZE]; //lli loop handle + int16_t etb_ch_id; + slist_t next; +}; + +typedef struct { + csi_dev_t dev; + slist_t head; + uint32_t alloc_status; + uint32_t ch_num; + void *priv; +} csi_dma_t; + +/** + \brief Init dma controller + \param[in] dma the dma controller operate handle + \param[in] ctrl_id the dma controller id + \return csi error code +*/ +csi_error_t csi_dma_init(csi_dma_t *dma, int8_t ctrl_id); + +/** + \brief Uninit dma controller + \param[in] dma the dma controller operate handle + \return none +*/ +void csi_dma_uninit(csi_dma_t *dma); + +/** + \brief Alloc a dma channel + \param[in] dma_ch the dma channel operate handle + \param[in] ch_id the channel id of dma; when set -1, means auto alloc + \param[in] ctrl_id the dma controller id; when set -1, means auto alloc + \return csi error code +*/ +csi_error_t csi_dma_ch_alloc(csi_dma_ch_t *dma_ch, int8_t ch_id, int8_t ctrl_id); + +/** + \brief Free a dma channel + \param[in] dma_ch the dma channel operate handle + \return none +*/ +void csi_dma_ch_free(csi_dma_ch_t *dma_ch); + +/** + \brief Config a dma channel + \param[in] dma_ch the dma channel operate handle + \param[in] config the config structure for dma channel + \return csi error code +*/ +csi_error_t csi_dma_ch_config(csi_dma_ch_t *dma_ch, csi_dma_ch_config_t *config); + +/** + \brief Start a dma channel + \param[in] dma_ch the dma channel operate handle + \param[in] psrcaddr transfer source address + \param[in] pdstaddr transfer destination address + \param[in] length transfer length (unit: bytes), if set data_width is 16, the length should be the multiple of 2, and + if set data_width is 32, the length should be the multiple of 4 + \return none +*/ +void csi_dma_ch_start(csi_dma_ch_t *dma_ch, void *srcaddr, void *dstaddr, uint32_t length); + +/** + \brief Stop a dma channel + \param[in] dma_ch the dma channel operate handle + \return none +*/ +void csi_dma_ch_stop(csi_dma_ch_t *dma_ch); + +/** + \brief Attach the callback handler to DMA channel + \param[in] dma_ch operate handle. + \param[in] callback callback function + \param[in] arg user can define it by himself as callback's param + \return error code +*/ +csi_error_t csi_dma_ch_attach_callback(csi_dma_ch_t *dma_ch, void *callback, void *arg); + +/** + \brief detach the callback handler + \param[in] uart operate handle. +*/ +void csi_dma_ch_detach_callback(csi_dma_ch_t *dma_ch); + +/** + \brief enable dma power manage + \param[in] dma dma handle to operate. + \return error code +*/ +csi_error_t csi_dma_enable_pm(csi_dma_t *dma); + +/** + \brief disable dma power manage + \param[in] dma dma handle to operate. +*/ +void csi_dma_disable_pm(csi_dma_t *dma); + +#ifdef __cplusplus +} +#endif + +#endif /* _CSI_DMA_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/drv_fft.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/drv_fft.h new file mode 100644 index 00000000000..62bcc8176e9 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/drv_fft.h @@ -0,0 +1,83 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv_fft.h + * @brief header file for gpio driver + * @version V1.0 + * @date 11. Nov 2017 + * @model fft + ******************************************************************************/ + +#ifndef _CSI_FFT_H_ +#define _CSI_FFT_H_ + + +#include +#include +#include +//#include + +#ifdef __cplusplus + extern "C" { +#endif + +typedef enum { + // 512-point FFT + CSKY_MCA_FFT_LEN_512 = 0x1, + // 256-point FFT + CSKY_MCA_FFT_LEN_256 = 0x2, + // 128-point FFT + CSKY_MCA_FFT_LEN_128 = 0x4, + // 64-point FFT + CSKY_MCA_FFT_LEN_64 = 0x8, + // 32-point FFT + CSKY_MCA_FFT_LEN_32 = 0x10, + // 16-point FFT + CSKY_MCA_FFT_LEN_16 = 0x20, +} csky_mca_fft_len_t; + +/* 8-bit fixed-point numeric type in user-defined format */ +typedef int8_t fxp8_t; +/* 16-bit fixed-point numeric type in user-defined format */ +typedef int16_t fxp16_t; +/* 24-bit fixed-point numeric type in user-defined format */ +typedef int32_t fxp24_t; +/* 32-bit fixed-point numeric type in user-defined format */ +typedef int32_t fxp32_t; +/* 64-bit fixed-point numeric type in user-defined format */ +typedef int64_t fxp64_t; + +/* 8-bit fixed-point numeric type in 1.0.7 format */ +typedef fxp8_t q7_t; +/* 16-bit fixed-point numeric type in 1.0.15 format */ +typedef fxp16_t q15_t; +/* 32-bit fixed-point numeric type in 1.15.16 format */ +typedef fxp32_t q16_t; + +void csky_mca_rfft_fxp32(csky_mca_fft_len_t fft_len, const fxp32_t *input, size_t input_size, fxp32_t *output); +void csky_mca_cfft_fxp32(csky_mca_fft_len_t fft_len, const fxp32_t *input, fxp32_t *output); +void csky_mca_rifft_fxp32(csky_mca_fft_len_t fft_len, const fxp32_t *input, fxp32_t *output); +void csky_mca_cifft_fxp32(csky_mca_fft_len_t fft_len, const fxp32_t *input, fxp32_t *output); +void csky_mca_power_spectrum_fxp32(csky_mca_fft_len_t fft_len, const fxp32_t *input, size_t input_size, fxp64_t *output); + +#ifdef __cplusplus +} +#endif + +#endif /* _CSI_FFT_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ecdh.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ecdh.h new file mode 100644 index 00000000000..5e9acf7899a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ecdh.h @@ -0,0 +1,92 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/ecdh.h + * @brief Header File for ECDH Driver + * @version V1.0 + * @date 9. May 2023 + * @model ecdh + ******************************************************************************/ + +#ifndef _DRV_ECDH_H_ +#define _DRV_ECDH_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** +\brief ECDH Ctrl Block +*/ +typedef struct { + csi_dev_t dev; + void *priv; +} csi_ecdh_t; + +/** + \brief Initialize ECDH interface. Initializes the resources needed for the ECDH interface + \param[in] ecdh Handle to operate + \param[in] idx Device id + \return Error code \ref csi_error_t +*/ +csi_error_t csi_ecdh_init(csi_ecdh_t *ecdh, uint32_t idx); + +/** + \brief De-initialize ECDH interface. Stops operation and releases the software resources used by the interface + \param[in] ecdh Dandle to operate + \return None +*/ +void csi_ecdh_uninit(csi_ecdh_t *ecdh); + +/** + \brief Load curve param to engin + \param[in] ecdh Handle to operate + \param[in] type Pointer to \ref csi_curve_type_t + \return Error code \ref csi_error_t +*/ +csi_error_t csi_ecdh_load_curve(csi_ecdh_t *ecdh, csi_curve_type_t type); + +/** + \brief ECDH generate key pair + \param[in] ecdh Handle to operate + \param[out] prikey Pointer to the private key buf + \param[out] pubkey Pointer to the public key buf + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_ecdh_gen_keypair(csi_ecdh_t *ecdh, uint8_t *prikey, uint8_t *pubkey); + +/** + \brief ECDH generate secret key + \param[in] ecdh Handle to operate + \param[in] prikey Pointer to the private key buf + \param[in] pubkey Pointer to the public key buf + \param[out] sk Pointer to the secret key buf + \param[out] sk_len The secret key length + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_ecdh_calc_secret(csi_ecdh_t *ecdh, const uint8_t *privkey, const uint8_t *pubkey, uint8_t *sk, uint32_t *sk_len); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_ECDH_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ecdsa.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ecdsa.h new file mode 100644 index 00000000000..0c034ebd208 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ecdsa.h @@ -0,0 +1,112 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/ecdsa.h + * @brief Header File for ECDSA Driver + * @version V1.0 + * @date 9. May 2023 + * @model ecdsa + ******************************************************************************/ + +#ifndef _DRV_ECDSA_H_ +#define _DRV_ECDSA_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** +\brief EC curve type +*/ +typedef enum { + CSI_CURVES_SECP256K1 = 0U, /* SECG curve over a 256 bit prime field */ + CSI_CURVES_SECP384R1, /* NIST/SECG curve over a 384 bit prime field */ + CSI_CURVES_SECP521R1, /* NIST/SECG curve over a 521 bit prime field */ + CSI_CURVES_BRAINPOOL256R1, /* RFC 5639 curve over a 256 prime field */ + CSI_CURVES_BRAINPOOL256T1, /* RFC 5639 curve over a 256 prime field */ + CSI_CURVES_BRAINPOOL512R1, /* RFC 5639 curve over a 512 prime field */ + CSI_CURVES_BRAINPOOL512T1, /* RFC 5639 curve over a 512 prime field */ +} csi_curve_type_t; + +/** +\brief ECDSA Ctrl Block +*/ +typedef struct { + csi_dev_t dev; + void *priv; +} csi_ecdsa_t; + +/** + \brief Initialize ECDSA interface. Initializes the resources needed for the ECDSA interface + \param[in] ecdsa Handle to operate + \param[in] idx Device id + \return Error code \ref csi_error_t +*/ +csi_error_t csi_ecdsa_init(csi_ecdsa_t *ecdsa, uint32_t idx); + +/** + \brief De-initialize ECDSA interface. Stops operation and releases the software resources used by the interface + \param[in] ecdsa Dandle to operate + \return None +*/ +void csi_ecdsa_uninit(csi_ecdsa_t *ecdsa); + +/** + \brief Load curve param to engin + \param[in] ecdsa Handle to operate + \param[in] type Pointer to \ref csi_curve_type_t + \return Error code \ref csi_error_t +*/ +csi_error_t csi_ecdsa_load_curve(csi_ecdsa_t *ecdsa, csi_curve_type_t type); + +/** + \brief Ecdsa Sign + \param[in] ecdsa Handle to operate + \param[in] prikey Pointer to the private key buf + \param[in] prikey_len The private key length + \param[in] dgst Pointer to the digest buf + \param[in] dgst_len The digest length + \param[out] sig Pointer to the signature buf + \param[out] sig_len The signature length + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_ecdsa_sign(csi_ecdsa_t *ecdsa, const uint8_t *prikey, uint32_t prikey_len, + const uint8_t *dgst, uint32_t dgst_len, uint8_t *sig, uint32_t *sig_len); + +/** + \brief Ecdsa Verify + \param[in] ecdsa Handle to operate + \param[in] pubkey Pointer to the public key buf + \param[in] prikey_len The public key length + \param[in] dgst Pointer to the digest buf + \param[in] dgst_len The digest length + \param[in] sig Pointer to the signature buf + \param[in] sig_len The signature length + \return Error code \ref Csi_error_t +*/ +csi_error_t csi_ecdsa_verify(csi_ecdsa_t *ecdsa, const uint8_t *pubkey, uint32_t pubkey_len, + const uint8_t *dgst, uint32_t gst_len, const uint8_t *sig, uint32_t sig_len); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_ECDSA_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eflash.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eflash.h new file mode 100644 index 00000000000..8d6c41d0f65 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eflash.h @@ -0,0 +1,140 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file eflash.h + * @brief header file for eflash driver + * @version V1.0 + * @date 02. June 2017 + * @model eflash + ******************************************************************************/ +#ifndef _DRV_EFLASH_H_ +#define _DRV_EFLASH_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** +\brief Flash information +*/ +typedef struct { + uint32_t flash_size; ///< Chip End address (start+size-1) + uint32_t sector_size; ///< Uniform sector size in bytes + uint32_t erased_value; ///< erased value +} csi_eflash_info_t; + +/** +\brief Flash Status +*/ +typedef struct { + uint32_t busy : 1; ///< Flash busy flag + uint32_t error : 1; ///< Read/Program/Erase error flag (cleared on start of next operation) +} eflash_status_t; + +/// definition for eflash handle. +typedef struct { + csi_dev_t dev; + void *arg; + csi_eflash_info_t eflashinfo; + uint16_t prog; + uint16_t erase; + void *priv; +} csi_eflash_t; + +// Function documentation + +/** + \brief Initialize EFLASH Interface. 1. Initializes the resources needed for the EFLASH interface 2.registers event callback function + \param[in] eflash eflash handle to operate. + \param[in] idx device id + \param[in] arg User can define it by himself as callback's param + \return error code +*/ +csi_error_t csi_eflash_init(csi_eflash_t *eflash, int32_t idx, void *arg); + +/** + \brief De-initialize EFLASH Interface. stops operation and releases the software resources used by the interface + \param[in] eflash eflash handle to operate. + \return error code +*/ +csi_error_t csi_eflash_uninit(csi_eflash_t *eflash); + +/** + \brief Read data from Flash. + \param[in] eflash eflash handle to operate. + \param[in] offset Data address. + \param[out] data Pointer to a buffer storing the data read from Flash. + \param[in] size Number of data items to read. + \return error code +*/ +csi_error_t csi_eflash_read(csi_eflash_t *eflash, uint32_t offset, void *data, uint32_t size); + +/** + \brief Program data to Flash. + \param[in] eflash eflash handle to operate. + \param[in] offset Data address. + \param[in] data Pointer to a buffer containing the data to be programmed to Flash. + \param[in] size Number of data items to program. + \return error code +*/ +csi_error_t csi_eflash_program(csi_eflash_t *eflash, uint32_t offset, const void *data, uint32_t size); + +/** + \brief Erase Flash Sector. + \param[in] eflash eflash handle to operate. + \param[in] offset flash address, flash address need sector size aligned + \param[in] size erase size + \return error code +*/ +csi_error_t csi_eflash_erase(csi_eflash_t *eflash, uint32_t offset,uint32_t size); + +/** + \brief Erase whole flash + \param[in] eflash eflash handle to operate. + \return error code +*/ +csi_error_t csi_eflash_erase_chip(csi_eflash_t *eflash); + +/** + \brief Get Flash information. + \param[in] eflash eflash handle to operate. +*/ +void csi_eflash_dev_info(csi_eflash_t *eflash,csi_eflash_info_t *eflash_info); + +/** + \brief enable eflash power manage + \param[in] eflash eflash handle to operate. + \return error code +*/ +csi_error_t csi_eflash_enable_pm(csi_eflash_t *eflash); + +/** + \brief disable eflash power manage + \param[in] eflash eflash handle to operate. +*/ +void csi_eflash_disable_pm(csi_eflash_t *eflash); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_EFLASH_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/efuse.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/efuse.h new file mode 100644 index 00000000000..2c697074e6e --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/efuse.h @@ -0,0 +1,93 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/efuse.h + * @brief Header File for EFUSE Driver + * @version V1.0 + * @date 22. Mar 2020 + * @model efuse + ******************************************************************************/ +#ifndef _DEV_EFUSEC_H_ +#define _DEV_EFUSEC_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t start; ///< Efuse start address + uint32_t end; ///< Efuse end address + uint32_t size; ///< Efuse size +} csi_efuse_info_t; + +typedef struct { + csi_dev_t dev; + csi_efuse_info_t info; +} csi_efuse_t; + +/** + \brief Initialize EFUSEC Interface. 1. Initializes the resources needed for the EFUSEC interface + \param[in] idx Device id + \return Error code +*/ +csi_error_t csi_efuse_init(csi_efuse_t *efuse, int32_t idx); + +/** + \brief De-initialize EFUSEC Interface. stops operation and releases the software resources used by the interface + \param[in] efuse Efuse efuse to operate. + \return None +*/ +void csi_efuse_uninit(csi_efuse_t *efuse); + +/** + \brief Read data from Efuse. + \param[in] efuse Efuse handle to operate. + \param[in] addr Data address. + \param[out] data Pointer to a buffer storing the data read from Efuse. + \param[in] size Number of data items to read. + \return Number of data items read or error code +*/ +int32_t csi_efuse_read(csi_efuse_t *efuse, uint32_t addr, void *data, uint32_t size); + +/** + \brief Program data to Efuse. + \param[in] efuse Efuse handle to operate. + \param[in] addr Data address. + \param[in] data Pointer to a buffer containing the data to be programmed to Efuse. + \param[in] cnt Number of data items to program. + \return number of data items programmed or error code +*/ +int32_t csi_efuse_program(csi_efuse_t *efuse, uint32_t addr, const void *data, uint32_t size); + +/** + \brief Get Efuse information. + \param[in] efuse Efuse handle to operate. + \param[out] info Efuse info \refs csi_efuse_info_t. + \return Error code +*/ +csi_error_t csi_efuse_get_info(csi_efuse_t *efuse, csi_efuse_info_t *info); + +#ifdef __cplusplus +} +#endif + +#endif /* _CSI_EFUSEC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/etb.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/etb.h new file mode 100644 index 00000000000..20dcfac7dfc --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/etb.h @@ -0,0 +1,102 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv_etb.h + * @brief header file for event trigger driver + * @version V1.0 + * @date 27. octorber 2017 + * @model etb + ******************************************************************************/ + +#ifndef _DRV_ETB_H_ +#define _DRV_ETB_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ETB_HARDWARE_TRIG = 0, ///< etb channel inout is hardware trigger. + ETB_SOFTWARE_TRIG ///< etb channel inout is software trigger. +} csi_etb_trig_mode_t; + +typedef enum { + ETB_CH_ONE_TRIGGER_ONE = 0, ///< one device trig one deivce + ETB_CH_ONE_TRIGGER_MORE, ///< one device trig two for more device + ETB_CH_MORE_TRIGGER_ONE ///< two or more device trig one deivce +} csi_etb_ch_type_t; + +typedef struct { + uint8_t src_ip; ///< a specific number represent a location in an source trigger location map to trigger other ip(s). + uint8_t dst_ip; ///< a specific number represent an location in an dest trigger map to wait signal(s) from source ip(s) or location(s). + csi_etb_trig_mode_t trig_mode; ///< the input source is hardware trigger or software trigger. + csi_etb_ch_type_t ch_type; ///< channel type +} csi_etb_config_t; + +/** + \brief Init the etb device + \return error code +*/ +csi_error_t csi_etb_init(void); + +/** + \brief Uninit the etb device + \return none +*/ +void csi_etb_uninit(void); + +/** + \brief alloc an etb channel + \param[in] ch_mode etb channel work mode + \return channel id or CSI_ERROR +*/ +int32_t csi_etb_ch_alloc(csi_etb_ch_type_t ch_type); + +/** + \brief free an etb channel + \param[in] ch_id etb channel work mode + \return none +*/ +void csi_etb_ch_free(int32_t ch_id); + +/** + \brief config etb channel + \param[in] ch_id etb channel id + \param[in] config the config structure for etb channel + \return csi error code +*/ +csi_error_t csi_etb_ch_config(int32_t ch_id, csi_etb_config_t *config); + +/** + \brief start an etb channel + \param[in] ch_id etb channel id + \return none +*/ +void csi_etb_ch_start(int32_t ch_id); + +/** + \brief stop an etb channel + \param[in] etb etb channel id + \return none +*/ +void csi_etb_ch_stop(int32_t ch_id); + +#endif /* _CSI_ETB_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth.h new file mode 100644 index 00000000000..3a2aedb4538 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth.h @@ -0,0 +1,111 @@ +/** + * Copyright (C) 2016 CSI Project. All rights reserved. + * + * Licensed 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 _CSI_NET_H_ +#define _CSI_NET_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define CSI_ETH_VERSION_MAJOR_MINOR(major,minor) (((major) << 8) | (minor)) + +/** +\brief Driver Version +*/ +typedef struct csi_driver_version { + uint16_t api; ///< API version + uint16_t drv; ///< Driver version +} csi_drv_version_t; + +/* General return codes */ +#define CSI_ETH_OK 0 ///< Operation succeeded +#define CSI_ETH_ERROR CSI_DRV_ERRNO_ETH_BASE+1 ///< Unspecified error +#define CSI_ETH_ERROR_BUSY CSI_DRV_ERRNO_ETH_BASE+2 ///< Driver is busy +#define CSI_ETH_ERROR_TIMEOUT CSI_DRV_ERRNO_ETH_BASE+3 ///< Timeout occurred +#define CSI_ETH_ERROR_UNSUPPORTED CSI_DRV_ERRNO_ETH_BASE+4 ///< Operation not supported +#define CSI_ETH_ERROR_PARAMETER CSI_DRV_ERRNO_ETH_BASE+5 ///< Parameter error +#define CSI_ETH_ERROR_SPECIFIC CSI_DRV_ERRNO_ETH_BASE+6 ///< Start of driver specific errors + +/** +\brief General power states +*/ +typedef enum eth_power_state { + CSI_ETH_POWER_OFF, ///< Power off: no operation possible + CSI_ETH_POWER_LOW, ///< Low Power mode: retain state, detect and signal wake-up events + CSI_ETH_POWER_FULL ///< Power on: full operation at maximum performance +} eth_power_state_t; + +/** +\brief Ethernet Media Interface type +*/ +#define CSI_ETH_INTERFACE_MII (0) ///< Media Independent Interface (MII) +#define CSI_ETH_INTERFACE_RMII (1) ///< Reduced Media Independent Interface (RMII) +#define CSI_ETH_INTERFACE_SMII (2) ///< Serial Media Independent Interface (SMII) + +/** +\brief Ethernet link speed +*/ +#define CSI_ETH_SPEED_10M (0) ///< 10 Mbps link speed +#define CSI_ETH_SPEED_100M (1) ///< 100 Mbps link speed +#define CSI_ETH_SPEED_1G (2) ///< 1 Gpbs link speed + +/** +\brief Ethernet duplex mode +*/ +#define CSI_ETH_DUPLEX_HALF (0) ///< Half duplex link +#define CSI_ETH_DUPLEX_FULL (1) ///< Full duplex link + +/** +\brief Ethernet auto-negotiation +*/ +#define CSI_ETH_AUTONEG_DISABLE (0) ///< Disable auto-negotiation +#define CSI_ETH_AUTONEG_ENABLE (1) ///< Enable auto-negotiation + +/** +\brief Ethernet link state +*/ +typedef enum eth_link_state { + ETH_LINK_DOWN, ///< Link is down + ETH_LINK_UP ///< Link is up +} eth_link_state_t; + +/** +\brief Ethernet link information +*/ +typedef volatile struct eth_link_info { + uint32_t speed : 2; ///< Link speed: 0= 10 MBit, 1= 100 MBit, 2= 1 GBit + uint32_t duplex : 1; ///< Duplex mode: 0= Half, 1= Full + uint32_t autoneg : 1; ///< Set the interface to Auto Negotiation mode of transmission parameters + uint32_t loopback : 1; ///< Set the interface into a Loop-back test mode + uint32_t isolation : 1; ///< Set to indicate electrical isolation of PHY interface from MII/RMII interface + uint32_t reserved : 26; +} eth_link_info_t; + +/** +\brief Ethernet MAC Address +*/ +typedef struct eth_mac_addr { + uint8_t b[6]; ///< MAC Address (6 bytes), MSB first +} eth_mac_addr_t; + +#ifdef __cplusplus +} +#endif + +#endif /* CSI_NET_H_ */ + diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth_mac.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth_mac.h new file mode 100644 index 00000000000..bc5757d2d27 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth_mac.h @@ -0,0 +1,377 @@ +/** + * Copyright (C) 2016 CSI Project. All rights reserved. + * + * Licensed 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 _CSI_ETH_H_ +#define _CSI_ETH_H_ + +#include +#include "drv/eth.h" +#include "drv/eth_phy.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *eth_mac_handle_t; + +#define MAX_FRAMELEN 1518 /* (note: maximum ethernet frame length would be 1518) */ + +#define CSI_ETH_MAC_API_VERSION CSI_DRIVER_VERSION_MAJOR_MINOR(2,1) /* API version */ + +#define _CSI_Driver_ETH_MAC_(n) Driver_ETH_MAC##n +#define CSI_Driver_ETH_MAC_(n) _CSI_Driver_ETH_MAC_(n) + +/****** Ethernet MAC Control Codes *****/ + +#define CSI_ETH_MAC_CONFIGURE (0x01) ///< Configure MAC; arg = configuration +#define CSI_ETH_MAC_CONTROL_TX (0x02) ///< Transmitter; arg: 0=disabled (default), 1=enabled +#define CSI_ETH_MAC_CONTROL_RX (0x03) ///< Receiver; arg: 0=disabled (default), 1=enabled +#define CSI_ETH_MAC_FLUSH (0x04) ///< Flush buffer; arg = CSI_ETH_MAC_FLUSH_... +#define CSI_ETH_MAC_SLEEP (0x05) ///< Sleep mode; arg: 1=enter and wait for Magic packet, 0=exit +#define CSI_ETH_MAC_VLAN_FILTER (0x06) ///< VLAN Filter for received frames; arg15..0: VLAN Tag; arg16: optional CSI_ETH_MAC_VLAN_FILTER_ID_ONLY; 0=disabled (default) +#define DRV_ETH_MAC_ADJUST_LINK (0x07) ///< Adjust MAC link state according to phy state; arg: phy handle +#define DRV_ETH_MAC_CONTROL_IRQ (0x08) ///< Interrupt request; arg: 0=disable, 1=enable + +/*----- Ethernet MAC Configuration -----*/ +#define CSI_ETH_MAC_SPEED_Pos 0 +#define CSI_ETH_MAC_SPEED_Msk (3UL << CSI_ETH_MAC_SPEED_Pos) +#define CSI_ETH_MAC_SPEED_10M (CSI_ETH_SPEED_10M << CSI_ETH_MAC_SPEED_Pos) ///< 10 Mbps link speed +#define CSI_ETH_MAC_SPEED_100M (CSI_ETH_SPEED_100M << CSI_ETH_MAC_SPEED_Pos) ///< 100 Mbps link speed +#define CSI_ETH_MAC_SPEED_1G (CSI_ETH_SPEED_1G << CSI_ETH_MAC_SPEED_Pos) ///< 1 Gpbs link speed +#define CSI_ETH_MAC_DUPLEX_Pos 2 +#define CSI_ETH_MAC_DUPLEX_Msk (1UL << CSI_ETH_MAC_DUPLEX_Pos) +#define CSI_ETH_MAC_DUPLEX_HALF (CSI_ETH_DUPLEX_HALF << CSI_ETH_MAC_DUPLEX_Pos) ///< Half duplex link +#define CSI_ETH_MAC_DUPLEX_FULL (CSI_ETH_DUPLEX_FULL << CSI_ETH_MAC_DUPLEX_Pos) ///< Full duplex link +#define CSI_ETH_MAC_LOOPBACK (1UL << 4) ///< Loop-back test mode +#define CSI_ETH_MAC_CHECKSUM_OFFLOAD_RX (1UL << 5) ///< Receiver Checksum offload +#define CSI_ETH_MAC_CHECKSUM_OFFLOAD_TX (1UL << 6) ///< Transmitter Checksum offload +#define CSI_ETH_MAC_ADDRESS_BROADCAST (1UL << 7) ///< Accept frames with Broadcast address +#define CSI_ETH_MAC_ADDRESS_MULTICAST (1UL << 8) ///< Accept frames with any Multicast address +#define CSI_ETH_MAC_ADDRESS_ALL (1UL << 9) ///< Accept frames with any address (Promiscuous Mode) + +/*----- Ethernet MAC Flush Flags -----*/ +#define CSI_ETH_MAC_FLUSH_RX (1UL << 0) ///< Flush Receive buffer +#define CSI_ETH_MAC_FLUSH_TX (1UL << 1) ///< Flush Transmit buffer + +/*----- Ethernet MAC VLAN Filter Flag -----*/ +#define CSI_ETH_MAC_VLAN_FILTER_ID_ONLY (1UL << 16) ///< Compare only the VLAN Identifier (12-bit) + + +/****** Ethernet MAC Frame Transmit Flags *****/ +#define CSI_ETH_MAC_TX_FRAME_FRAGMENT (1UL << 0) ///< Indicate frame fragment +#define CSI_ETH_MAC_TX_FRAME_EVENT (1UL << 1) ///< Generate event when frame is transmitted +#define CSI_ETH_MAC_TX_FRAME_TIMESTAMP (1UL << 2) ///< Capture frame time stamp + + +/****** Ethernet MAC Timer Control Codes *****/ +#define CSI_ETH_MAC_TIMER_GET_TIME (0x01) ///< Get current time +#define CSI_ETH_MAC_TIMER_SET_TIME (0x02) ///< Set new time +#define CSI_ETH_MAC_TIMER_INC_TIME (0x03) ///< Increment current time +#define CSI_ETH_MAC_TIMER_DEC_TIME (0x04) ///< Decrement current time +#define CSI_ETH_MAC_TIMER_SET_ALCSI (0x05) ///< Set alarm time +#define CSI_ETH_MAC_TIMER_ADJUST_CLOCK (0x06) ///< Adjust clock frequency; time->ns: correction factor * 2^31 + + +/** +\brief Ethernet MAC Time +*/ +typedef struct eth_mac_time { + uint32_t ns; ///< Nano seconds + uint32_t sec; ///< Seconds +} eth_mac_time_t; + + +/****** Ethernet MAC Event *****/ +#define CSI_ETH_MAC_EVENT_RX_FRAME (1UL << 0) ///< Frame Received +#define CSI_ETH_MAC_EVENT_TX_FRAME (1UL << 1) ///< Frame Transmitted +#define CSI_ETH_MAC_EVENT_WAKEUP (1UL << 2) ///< Wake-up (on Magic Packet) +#define CSI_ETH_MAC_EVENT_TIMER_ALCSI (1UL << 3) ///< Timer Alarm +#define CSI_ETH_MAC_EVENT_LINK_CHANGE (1UL << 4) ///< Link state + +typedef void (*eth_event_cb_t)(int32_t idx, uint32_t event); ///< Pointer to \ref eth_event_cb_t : Signal Ethernet Event. + +typedef enum { + FRAME_FILTER_RULE_POSITIVE_MATCHING = 0, /*!< Specifies that a filter should match a given pattern */ + FRAME_FILTER_RULE_NEGATIVE_MATCHING = 1, /*!< Specifies that a filter should NOT match a given pattern */ +} frame_filter_rule_t; + +/** +\brief Ethernet MAC Capabilities +*/ +typedef struct eth_capabilities { + uint32_t checksum_offload_rx_ip4 : 1; ///< 1 = IPv4 header checksum verified on receive + uint32_t checksum_offload_rx_ip6 : 1; ///< 1 = IPv6 checksum verification supported on receive + uint32_t checksum_offload_rx_udp : 1; ///< 1 = UDP payload checksum verified on receive + uint32_t checksum_offload_rx_tcp : 1; ///< 1 = TCP payload checksum verified on receive + uint32_t checksum_offload_rx_icmp : 1; ///< 1 = ICMP payload checksum verified on receive + uint32_t checksum_offload_tx_ip4 : 1; ///< 1 = IPv4 header checksum generated on transmit + uint32_t checksum_offload_tx_ip6 : 1; ///< 1 = IPv6 checksum generation supported on transmit + uint32_t checksum_offload_tx_udp : 1; ///< 1 = UDP payload checksum generated on transmit + uint32_t checksum_offload_tx_tcp : 1; ///< 1 = TCP payload checksum generated on transmit + uint32_t checksum_offload_tx_icmp : 1; ///< 1 = ICMP payload checksum generated on transmit + uint32_t media_interface : 2; ///< Ethernet Media Interface type + uint32_t mac_address : 1; ///< 1 = driver provides initial valid MAC address + uint32_t event_rx_frame : 1; ///< 1 = callback event generated + uint32_t event_tx_frame : 1; ///< 1 = callback event generated + uint32_t event_wakeup : 1; ///< 1 = wakeup event generated + uint32_t precision_timer : 1; ///< 1 = Precision Timer supported + uint32_t reserved : 15; ///< Reserved (must be zero) +} eth_capabilities_t; + +/** + * Structure describing a frame filter list item + */ +typedef struct { + uint32_t id; /*!< Unique identifier for a packet filter item */ + frame_filter_rule_t rule; /*!< Filter matches are either POSITIVE or NEGATIVE matching */ + uint16_t offset; /*!< Offset in bytes to start filtering (referenced to the start of the ethernet packet) */ + uint16_t mask_size; /*!< Size of the mask in bytes */ + uint8_t *mask; /*!< Pattern mask bytes to be ANDed with the pattern eg. "\xff00" (must be in network byte order) */ + uint8_t *pattern; /*!< Pattern bytes used to filter eg. "\x0800" (must be in network byte order) */ + bool enabled_status; /*!< When returned from mhd_get_packet_filters, indicates if the filter is enabled */ +} eth_frame_filter_t; + +struct eth_frame_filter_list { + struct eth_frame_filter_list *next; +}; + +typedef struct eth_frame_filter_list eth_frame_filter_list_t; + +typedef struct { + eth_event_cb_t cb_event; + eth_capabilities_t capabilities; +} eth_mac_priv_t; + +/** + \brief Get driver version. + \param[in] handle ethernet handle + \return ethernet version including chip version and driver version +*/ +csi_drv_version_t csi_eth_mac_get_version(eth_mac_handle_t handle); + +/** + \brief Get driver capabilities. + \param[in] idx device id + \return ethernet capabilities +*/ +eth_capabilities_t csi_eth_mac_get_capabilities(int32_t idx); + +/** + \brief This function is used to initialize Ethernet device and related resource, an event callback is registered. It is called when the middleware component like TCPIP starts operation. + \param[in] idx device id + \param[in] cb callback to handle ethernet event + \return return ethernet handle if success + */ +eth_mac_handle_t csi_eth_mac_initialize(int32_t idx, eth_event_cb_t cb_event); + +/** + \brief This function is used to de-initialize Ethernet device. It is called when the middleware component stops operation and releases the software resources used by the interface. + \param[in] handle ethernet handle + \return error code + */ +int32_t csi_eth_mac_uninitialize(eth_mac_handle_t handle); + +/** + \brief Connect phy device to mac device. + \param[in] handle_mac mac handle + \param[in] handle_phy phy handle +*/ +void csi_eth_mac_connect_phy(eth_mac_handle_t handle_mac, eth_phy_handle_t handle_phy); + +/** + \brief Control Ethernet MAC Device Power. + \param[in] handle ethernet handle + \param[in] state Power state + \return error code +*/ +int32_t csi_eth_mac_power_control(eth_mac_handle_t handle, eth_power_state_t state); + +/** + \brief Get Ethernet MAC Address. + \param[in] handle ethernet handle + \param[in] mac Pointer to address + \return error code +*/ +int32_t csi_eth_mac_get_macaddr(eth_mac_handle_t handle, eth_mac_addr_t *mac); + +/** + \brief Set Ethernet MAC Address. + \param[in] handle ethernet handle + \param[in] mac Pointer to address + \return error code +*/ +int32_t csi_eth_mac_set_macaddr(eth_mac_handle_t handle, const eth_mac_addr_t *mac); + +/** + \brief Configure Address Filter. + \param[in] handle ethernet handle + \param[in] addr Pointer to addresses + \param[in] num_addr Number of addresses to configure + \return error code +*/ +int32_t csi_eth_mac_set_addrfilter(eth_mac_handle_t handle, const eth_mac_addr_t *addr, uint32_t num_addr); + +/** + \brief Send Ethernet frame. + \param[in] handle ethernet handle + \param[in] frame Pointer to frame buffer with data to send + \param[in] len Frame buffer length in bytes + \param[in] flags Frame transmit flags (see CSI_ETH_MAC_TX_FRAME_...) + \return error code +*/ +int32_t csi_eth_mac_send_frame(eth_mac_handle_t handle, const uint8_t *frame, uint32_t len, uint32_t flags); + +/** + \brief Read data of received Ethernet frame. + \param[in] handle ethernet handle + \param[in] frame Pointer to frame buffer for data to read into + \param[in] len Frame buffer length in bytes + \return number of data bytes read or execution status + - value >= 0: number of data bytes read + - value < 0: error occurred, value is execution status as defined with execution_status +*/ +int32_t csi_eth_mac_read_frame(eth_mac_handle_t handle, uint8_t *frame, uint32_t len); + +/** + \brief Request data of received Ethernet frame. + csi_eth_mac_request_frame() and csi_eth_mac_release_frame() + must be called in pairs. + \param[in] handle ethernet handle + \param[in] frame Pointer to frame buffer pointer + \return number of data bytes read or execution status + - value >= 0: number of data bytes read + - value < 0: error occurred +*/ +int32_t csi_eth_mac_request_frame(eth_mac_handle_t handle, uint8_t **frame); + +/** + \brief Release current Ethernet frame. + csi_eth_mac_request_frame() and csi_eth_mac_release_frame() + must be called in pairs. + \param[in] handle ethernet handle + \return error code +*/ +int32_t csi_eth_mac_release_frame(eth_mac_handle_t handle); + +/** + \brief Get size of received Ethernet frame. + \param[in] handle ethernet handle + \return number of bytes in received frame +*/ +int32_t csi_eth_mac_get_rx_framesize(eth_mac_handle_t handle); + +/** + \brief Get time of received Ethernet frame. + \param[in] handle ethernet handle + \param[in] time Pointer to time structure for data to read into + \return error code +*/ +int32_t csi_eth_mac_get_rx_frametime(eth_mac_handle_t handle, eth_mac_time_t *time); + +/** + \brief Get time of transmitted Ethernet frame. + \param[in] handle ethernet handle + \param[in] time Pointer to time structure for data to read into + \return error code +*/ +int32_t csi_eth_mac_get_tx_frametime(eth_mac_handle_t handle, eth_mac_time_t *time); + +/** + \brief Control Ethernet Interface. + \param[in] handle ethernet handle + \param[in] control Operation + \param[in] arg Argument of operation (optional) + \return error code +*/ +int32_t csi_eth_mac_control(eth_mac_handle_t handle, uint32_t control, uint32_t arg); + +/** + \brief Control Precision Timer. + \param[in] handle ethernet handle + \param[in] control Operation + \param[in] time Pointer to time structure + \return error code +*/ +int32_t csi_eth_mac_control_time(eth_mac_handle_t handle, uint32_t control, eth_mac_time_t *time); + +/** + \brief Read Ethernet PHY Register through Management Interface. + \param[in] handle ethernet handle + \param[in] phy_addr 5-bit device address + \param[in] reg_addr 5-bit register address + \param[out] data Pointer where the result is written to + \return error code +*/ +int32_t csi_eth_mac_phy_read(eth_mac_handle_t handle, uint8_t phy_addr, uint8_t reg_addr, uint16_t *data); + +/** + \brief Write Ethernet PHY Register through Management Interface. + \param[in] handle ethernet handle + \param[in] phy_addr 5-bit device address + \param[in] reg_addr 5-bit register address + \param[in] data 16-bit data to write + \return error code +*/ +int32_t csi_eth_mac_phy_write(eth_mac_handle_t handle, uint8_t phy_addr, uint8_t reg_addr, uint16_t data); + +/** + \brief Callback function that signals a Ethernet Event. + \param[in] handle ethernet handle + \param[in] event event notification mask + \return none +*/ +void csi_eth_mac_signal_event(eth_mac_handle_t handle, uint32_t event); + +/** + \brief Add Frame Filter Setting with Filter ID. + \param[in] handle ethernet handle + \param[in] filter Pointer to filter setting + \return error code +*/ +int32_t csi_eth_mac_add_framefilter(eth_mac_handle_t handle, const eth_frame_filter_t *filter); + +/** + \brief Remove Frame Filter Setting. + \param[in] handle ethernet handle + \param[in] filter_id Frame Filter ID + \return error code +*/ +int32_t csi_eth_mac_remove_framefilter(eth_mac_handle_t handle, uint32_t filter_id); + +/** + \brief Enable/Disable Specified Frame Filter ID. + \param[in] handle ethernet handle + \param[in] filter_id Frame Filter ID + \param[in] en Enable or disable + \return error code +*/ +int32_t csi_eth_mac_en_framefilter(eth_mac_handle_t handle, uint32_t filter_id, bool en); + +/** + \brief Get frame filter table list. + \param[in] handle ethernet handle + \param[in] list frame filter table list + \param[in] count_out the count of filter setting added + \param[in] max_count max filter setting can be supported + \return error code +*/ +int32_t csi_eth_mac_get_framefilter(eth_mac_handle_t handle, eth_frame_filter_list_t *list, uint32_t *count_out, uint32_t max_count); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth_phy.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth_phy.h new file mode 100644 index 00000000000..5ef875654e4 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/eth_phy.h @@ -0,0 +1,124 @@ +/** + * Copyright (C) 2016 CSI Project. All rights reserved. + * + * Licensed 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 _CSI_ETH_PHY_H_ +#define _CSI_ETH_PHY_H_ + +#include "drv/eth.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *eth_phy_handle_t; + +#define CSI_ETH_PHY_API_VERSION CSI_ETH_VERSION_MAJOR_MINOR(2,1) /* API version */ + + +#define _CSI_Driver_ETH_PHY_(n) Driver_ETH_PHY##n +#define CSI_Driver_ETH_PHY_(n) _CSI_Driver_ETH_PHY_(n) + + +/****** Ethernet PHY Mode *****/ +#define CSI_ETH_PHY_SPEED_Pos 0 +#define CSI_ETH_PHY_SPEED_Msk (3UL << CSI_ETH_PHY_SPEED_Pos) +#define CSI_ETH_PHY_SPEED_10M (CSI_ETH_SPEED_10M << CSI_ETH_PHY_SPEED_Pos) ///< 10 Mbps link speed +#define CSI_ETH_PHY_SPEED_100M (CSI_ETH_SPEED_100M << CSI_ETH_PHY_SPEED_Pos) ///< 100 Mbps link speed +#define CSI_ETH_PHY_SPEED_1G (CSI_ETH_SPEED_1G << CSI_ETH_PHY_SPEED_Pos) ///< 1 Gpbs link speed +#define CSI_ETH_PHY_DUPLEX_Pos 2 +#define CSI_ETH_PHY_DUPLEX_Msk (1UL << CSI_ETH_PHY_DUPLEX_Pos) +#define CSI_ETH_PHY_DUPLEX_HALF (CSI_ETH_DUPLEX_HALF << CSI_ETH_PHY_DUPLEX_Pos) ///< Half duplex link +#define CSI_ETH_PHY_DUPLEX_FULL (CSI_ETH_DUPLEX_FULL << CSI_ETH_PHY_DUPLEX_Pos) ///< Full duplex link +#define CSI_ETH_PHY_AUTO_NEGOTIATE (1UL << 3) ///< Auto Negotiation mode +#define CSI_ETH_PHY_LOOPBACK (1UL << 4) ///< Loop-back test mode +#define CSI_ETH_PHY_ISOLATE (1UL << 5) ///< Isolate PHY from MII/RMII interface + +typedef int32_t (*csi_eth_phy_read_t)(uint8_t phy_addr, uint8_t reg_addr, uint16_t *data); ///< Read Ethernet PHY Register. +typedef int32_t (*csi_eth_phy_write_t)(uint8_t phy_addr, uint8_t reg_addr, uint16_t data); ///< Write Ethernet PHY Register. + +typedef struct { + csi_eth_phy_read_t phy_read; + csi_eth_phy_write_t phy_write; + eth_link_info_t link_info; +} eth_phy_priv_t; + +// Function documentation +/** + \brief Get driver version. + \param[in] handle ethernet phy handle + \return driver version +*/ +csi_drv_version_t csi_eth_phy_get_version(eth_phy_handle_t handle); + +/** + \brief Initialize Ethernet PHY Device. + \param[in] fn_read + \param[in] fn_write + \return ethernet phy handle +*/ +eth_phy_handle_t csi_eth_phy_initialize(csi_eth_phy_read_t fn_read, csi_eth_phy_write_t fn_write); + +/** + \brief De-initialize Ethernet PHY Device. + \param[in] handle ethernet phy handle + \return error code +*/ +int32_t csi_eth_phy_uninitialize(eth_phy_handle_t handle); + +/** + \brief Control Ethernet PHY Device Power. + \param[in] handle ethernet phy handle + \param[in] state Power state + \return error code +*/ +int32_t csi_eth_phy_power_control(eth_phy_handle_t handle, eth_power_state_t state); + +/** + \brief Set Ethernet Media Interface. + \param[in] handle ethernet phy handle + \param[in] interface Media Interface type + \return error code +*/ +int32_t csi_eth_phy_set_interface(eth_phy_handle_t handle, uint32_t interface); + +/** + \brief Set Ethernet PHY Device Operation mode. + \param[in] handle ethernet phy handle + \param[in] mode Operation Mode + \return error code +*/ +int32_t csi_eth_phy_set_mode(eth_phy_handle_t handle, uint32_t mode); + +/** + \brief Get Ethernet PHY Device Link state. + \param[in] handle ethernet phy handle + \return current link status \ref eth_link_state_t +*/ +eth_link_state_t csi_eth_phy_get_linkstate(eth_phy_handle_t handle); + +/** + \brief Get Ethernet PHY Device Link information. + \param[in] handle ethernet phy handle + \return current link parameters \ref eth_link_info_t +*/ +eth_link_info_t csi_eth_phy_get_linkinfo(eth_phy_handle_t handle); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/fft.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/fft.h new file mode 100644 index 00000000000..a3cd312b6e3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/fft.h @@ -0,0 +1,87 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/fft.h + * @brief Header File for FFT Driver + * @version V1.0 + * @date 11. Nov 2020 + * @model fft + ******************************************************************************/ + +#ifndef _DRV_FFT_H_ +#define _DRV_FFT_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ///< 512-point FFT + CSKY_MCA_FFT_LEN_512 = 0x1, + ///< 256-point FFT + CSKY_MCA_FFT_LEN_256 = 0x2, + ///< 128-point FFT + CSKY_MCA_FFT_LEN_128 = 0x4, + ///< 64-point FFT + CSKY_MCA_FFT_LEN_64 = 0x8, + ///< 32-point FFT + CSKY_MCA_FFT_LEN_32 = 0x10, + ///< 16-point FFT + CSKY_MCA_FFT_LEN_16 = 0x20, +} csky_mca_fft_len_t; + +/* 8-bit fixed-point numeric type in user-defined format */ +typedef int8_t fxp8_t; + +/* 16-bit fixed-point numeric type in user-defined format */ +typedef int16_t fxp16_t; + +/* 24-bit fixed-point numeric type in user-defined format */ +typedef int32_t fxp24_t; + +/* 32-bit fixed-point numeric type in user-defined format */ +typedef int32_t fxp32_t; + +/* 64-bit fixed-point numeric type in user-defined format */ +typedef int64_t fxp64_t; + +/* 8-bit fixed-point numeric type in 1.0.7 format */ +typedef fxp8_t q7_t; + +/* 16-bit fixed-point numeric type in 1.0.15 format */ +typedef fxp16_t q15_t; + +/* 32-bit fixed-point numeric type in 1.15.16 format */ +typedef fxp32_t q16_t; + +void csky_mca_rfft_fxp32(csky_mca_fft_len_t fft_len, const fxp32_t *input, size_t input_size, fxp32_t *output); +void csky_mca_cfft_fxp32(csky_mca_fft_len_t fft_len, const fxp32_t *input, fxp32_t *output); +void csky_mca_rifft_fxp32(csky_mca_fft_len_t fft_len, const fxp32_t *input, fxp32_t *output); +void csky_mca_cifft_fxp32(csky_mca_fft_len_t fft_len, const fxp32_t *input, fxp32_t *output); +void csky_mca_power_spectrum_fxp32(csky_mca_fft_len_t fft_len, const fxp32_t *input, size_t input_size, fxp64_t *output); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_FFT_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/gpio.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/gpio.h new file mode 100644 index 00000000000..e33545184b6 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/gpio.h @@ -0,0 +1,214 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/gpio.h + * @brief Header File for GPIO Driver + * @version V1.0 + * @date 8. Apr 2020 + * @model gpio + ******************************************************************************/ + +#ifndef _DRV_GPIO_H_ +#define _DRV_GPIO_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \enum csi_gpio_dir_t + * \brief GPIO dir define + */ +typedef enum { + GPIO_DIRECTION_INPUT = 0, ///< GPIO as input + GPIO_DIRECTION_OUTPUT, ///< GPIO as output +} csi_gpio_dir_t; + +/** + * \enum csi_gpio_pin_state_t + * \brief GPIO pin state define + */ +typedef enum { + GPIO_PIN_LOW = 0, ///< GPIO low level + GPIO_PIN_HIGH, ///< GPIO high level +} csi_gpio_pin_state_t; + +/** + * \enum csi_gpio_mode_t + * \brief GPIO mode define + */ +typedef enum { + GPIO_MODE_PULLNONE = 0, ///< Pull none + GPIO_MODE_PULLUP, ///< Pull up for input + GPIO_MODE_PULLDOWN, ///< Pull down for input + GPIO_MODE_OPEN_DRAIN, ///< Open drain mode for output + GPIO_MODE_PUSH_PULL, ///< Push-pull mode for output +} csi_gpio_mode_t; + +/** + * \enum csi_gpio_irq_mode_t + * \brief GPIO irq triger type + */ +typedef enum { + GPIO_IRQ_MODE_RISING_EDGE = 0, ///< Interrupt mode for rising edge + GPIO_IRQ_MODE_FALLING_EDGE, ///< Interrupt mode for falling edge + GPIO_IRQ_MODE_BOTH_EDGE, ///< Interrupt mode for both edge + GPIO_IRQ_MODE_LOW_LEVEL, ///< Interrupt mode for low level + GPIO_IRQ_MODE_HIGH_LEVEL, ///< Interrupt mode for high level +} csi_gpio_irq_mode_t; + +/** + * \struct csi_gpio_t + * \brief GPIO control block + */ + +typedef struct csi_gpio csi_gpio_t; +struct csi_gpio { + csi_dev_t dev; ///< Hw-dev info + void (*callback)(csi_gpio_t *gpio, uint32_t pins, void *arg); ///< Call-back of gpio port + void *arg; ///< User param passed to callback + void *priv; ///< User private param +}; + +/** + \brief Initialize GPIO Port handle + \param[in] gpio GPIO port handle + \param[in] port_idx GPIO port index + \return Error code +*/ +csi_error_t csi_gpio_init(csi_gpio_t *gpio, uint32_t port_idx); + +/** + \brief De-initialize GPIO pin.stops operation + releases the software resources used by the gpio-pin + \param[in] gpio GPIO port handle + \return None +*/ +void csi_gpio_uninit(csi_gpio_t *gpio); + +/** + \brief Config pin direction + \param[in] gpio GPIO port handle + \param[in] pin_mask Pin mask need to be set + \param[in] dir \ref csi_gpio_dir_t + \return Error code +*/ +csi_error_t csi_gpio_dir(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_dir_t dir); + +/** + \brief Config pin mode + If one of pins config error, then the rest of pins will not config, and function return CSI_ERROR + If one or more pin unsupport, function will return CSI_UNSUPPORT, but the other pin still configured + \param[in] gpio GPIO port handle + \param[in] pin_mask Pin mask need to be set + \param[in] mode \ref csi_gpio_mode_t + \return Error code +*/ +csi_error_t csi_gpio_mode(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_mode_t mode); + +/** + \brief Config gpio irq params + \param[in] gpio GPIO port handle + \param[in] pin_mask Pin mask need to be set + \param[in] mode Interrupt trigger mode \ref csi_gpio_irq_mode_t + \return Error code +*/ +csi_error_t csi_gpio_irq_mode(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_irq_mode_t mode); + +/** + \brief Enable or disable gpio pin interrupt + \param[in] gpio GPIO port handle + \param[in] pin_mask Pin mask need to be set + \param[in] enable 0:disable 1:enable + \return Error code +*/ +csi_error_t csi_gpio_irq_enable(csi_gpio_t *gpio, uint32_t pin_mask, bool enable); + +/** + \brief Set debounce of gpio when gpio configed as input + \param[in] gpio GPIO port handle + \param[in] pin_mask Pin mask need to be set + \param[in] enbale 0: disable 1:enable + \return Error code +*/ +csi_error_t csi_gpio_debounce(csi_gpio_t *gpio, uint32_t pin_mask, bool enable); +/** + \brief Set one or zero to the selected pin mask + \param[in] gpio GPIO port handle + \param[in] pin_mask Pin mask need to be set + \param[in] value Value to be set \ref csi_gpio_pin_state_t + \return None +*/ +void csi_gpio_write(csi_gpio_t *gpio, uint32_t pin_mask, csi_gpio_pin_state_t value); + +/** + \brief Toggle output gpio value,ex.if previous value is 1, then output 0 + \param[in] gpio GPIO port handle + \param[in] pin_mask Pin mask need to be set + \return None +*/ +void csi_gpio_toggle(csi_gpio_t *gpio, uint32_t pin_mask); + +/** + \brief Get the value of selected GPIO pin mask + \param[in] gpio GPIO port handle + \param[in] pin_mask Pin mask need to be set + \return According to the bit mask, the corresponding pin status is obtained +*/ +uint32_t csi_gpio_read(csi_gpio_t *gpio, uint32_t pin_mask); + +/** + \brief Attach the interrupt callback to the port + \param[in] gpio GPIO port handle + \param[in] callback Callback function + \param[in] arg User param passed to callback + \return Error code +*/ +csi_error_t csi_gpio_attach_callback(csi_gpio_t *gpio, void *callback, void *arg); + +/** + \brief Detach the interrupt callback to the port + \param[in] gpio GPIO port handle + \return None +*/ +void csi_gpio_detach_callback(csi_gpio_t *gpio); + +/** + \brief Enable gpio power manage + \param[in] gpio GPIO handle to operate + \return Error code +*/ +csi_error_t csi_gpio_enable_pm(csi_gpio_t *gpio); + +/** + \brief Disable gpio power manage + \param[in] gpio GPIO handle to operate + \return None +*/ +void csi_gpio_disable_pm(csi_gpio_t *gpio); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_GPIO_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/gpio_pin.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/gpio_pin.h new file mode 100644 index 00000000000..6023d4ce075 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/gpio_pin.h @@ -0,0 +1,143 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/gpio_pin.h + * @brief Header File for GPIO PIN Driver + * @version v1.0 + * @date 2020-06-28 + * @note Only one of gpio or gpio_pin interface can be selected + ******************************************************************************/ + +#ifndef _DRV_GPIO_PIN_H_ +#define _DRV_GPIO_PIN_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \struct csi_gpio_pin_t + * \brief GPIO PIN control block + */ + +typedef struct csi_gpio_pin csi_gpio_pin_t; +struct csi_gpio_pin { + csi_gpio_t *gpio; + uint32_t pin_idx; + void (*callback)(csi_gpio_pin_t *pin, void *arg); + void *arg; +}; + +/** + \brief Initialize GPIO pin handle + \param[in] pin GPIO pin handle + \param[in] pin_name GPIO pin name + \return Error code +*/ +csi_error_t csi_gpio_pin_init(csi_gpio_pin_t *pin, pin_name_t pin_name); + +/** + \brief De-initialize GPIO pin + \param[in] pin GPIO pin handle + \return None +*/ +void csi_gpio_pin_uninit(csi_gpio_pin_t *pin); + +/** + \brief Attach the interrupt callback to the GPIO pin + \param[in] pin GPIO pin handle + \param[in] callback Callback function + \param[in] arg User param passed to callback + \return Error code +*/ +csi_error_t csi_gpio_pin_attach_callback(csi_gpio_pin_t *pin, void *callback, void *arg); + +/** + \brief Config pin direction + \param[in] pin GPIO pin handle + \param[in] dir \ref csi_gpio_dir_t + \return Error code +*/ +csi_error_t csi_gpio_pin_dir(csi_gpio_pin_t *pin, csi_gpio_dir_t dir); + +/** + \brief Config pin mode + \param[in] pin GPIO pin handle + \param[in] mode \ref csi_gpio_mode_t + \return Error code +*/ +csi_error_t csi_gpio_pin_mode(csi_gpio_pin_t *pin, csi_gpio_mode_t mode); + +/** + \brief Config pin irq params + \param[in] pin GPIO pin handle + \param[in] mode Interrupt trigger mode \ref csi_gpio_irq_mode_t + \return Error code +*/ +csi_error_t csi_gpio_pin_irq_mode(csi_gpio_pin_t *pin, csi_gpio_irq_mode_t mode); + +/** + \brief Enable or disable gpio pin interrupt + \param[in] pin GPIO pin handle + \param[in] enable 0:disable 1:enable + \return Error code +*/ +csi_error_t csi_gpio_pin_irq_enable(csi_gpio_pin_t *pin, bool enable); + +/** + \brief Set debounce of pin when pin configed as input + \param[in] pin GPIO pin handle + \param[in] enbale 0: disable 1:enable + \return Error code +*/ +csi_error_t csi_gpio_pin_debounce(csi_gpio_pin_t *pin, bool enable); + +/** + \brief Set one or zero to specified pin + \param[in] pin GPIO pin handle + \param[in] value Value to be set \ref csi_gpio_pin_state_t + \return None +*/ +void csi_gpio_pin_write(csi_gpio_pin_t *pin, csi_gpio_pin_state_t value); + +/** + \brief Toggle output pin value,ex.if previous value is 1, then output 0 + \param[in] pin GPIO pin handle + \return None +*/ +void csi_gpio_pin_toggle(csi_gpio_pin_t *pin); + +/** + \brief Get the value of specified GPIO pin + \param[in] pin GPIO port handle + \return gpio pin state, \ref csi_gpio_pin_state_t +*/ +csi_gpio_pin_state_t csi_gpio_pin_read(csi_gpio_pin_t *pin); + +#ifdef __cplusplus +} +#endif + +#endif /* _GPIO_PIN_H_*/ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/hmac.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/hmac.h new file mode 100644 index 00000000000..b9298e19271 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/hmac.h @@ -0,0 +1,122 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ +/****************************************************************************** + * @file drv/hmac.h + * @brief Header File for HMAC + * @version V1.0 + * @date 27. Apri 2023 + * @model hmac + ******************************************************************************/ +#ifndef _DRV_HMAC_H_ +#define _DRV_HMAC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****** HMAC Event ******/ +typedef enum { + HMAC_EVENT_COMPLETE = 0U, /* Calculate completed */ + HMAC_EVENT_ERROR /* Calculate error */ +} csi_hmac_event_t; + +/****** HMAC Context ******/ +typedef struct { + csi_sha_mode_t mode; /* SHA mode */ + uint32_t total[2]; /* Number of bytes processed */ + uint8_t buffer[128]; /* Data block being processed */ +} csi_hmac_context_t; + +/****** HMAC Ctrl ******/ +typedef struct csi_hmac { + csi_dev_t dev; + void *priv; +}csi_hmac_t; + +/** + \brief Initialize MAC Interface. Initializes the resources needed for the MAC interface + \param[in] mac operate handle. + \param[in] idx index of mac + \return error code \ref csi_error_t +*/ +csi_error_t csi_hmac_init(csi_hmac_t *mac, uint32_t idx); + +/** + \brief De-initialize MAC Interface. stops operation and releases the software resources used by the interface + \param[in] mac mac handle to operate. + \return none +*/ +void csi_hmac_uninit(csi_hmac_t *mac); + +/** + \brief MAC set key function. + \param[in] mac mac handle to operate. + \param[in] key Pointer to the mac key. + \param[in] key_len Length of key. + \return error code \ref csi_error_t +*/ +csi_error_t csi_hmac_set_key(csi_hmac_t *mac, uint8_t *key, uint32_t key_len); + +/** + \brief MAC start operation function. + \param[in] mac mac handle to operate. + \param[in] context mac context pointer. + \param[in] mode sc_sha_mode_t. + \return error code \ref csi_error_t +*/ +csi_error_t csi_hmac_start(csi_hmac_t *mac, csi_hmac_context_t *context, csi_sha_mode_t mode); + +/** + \brief MAC start operation function. + \param[in] mac mac handle to operate. + \param[in] msg Pointer to the mac input message. + \param[in] msg_len Length of msg. + \return error code \ref csi_error_t +*/ +csi_error_t csi_hmac_update(csi_hmac_t *mac, csi_hmac_context_t *context, uint8_t *msg, uint32_t msg_len); + +/** + \brief MAC start operation function. + \param[in] mac mac handle to operate. + \param[out] out mac buffer, malloc by caller. + \param[out] out_len out mac length, + \return error code \ref csi_error_t +*/ +csi_error_t csi_hmac_finish(csi_hmac_t *mac, csi_hmac_context_t *context, uint8_t *out, uint32_t *out_len); + +/** + \brief MAC cacl operation function. + \param[in] mac mac handle to operate. + \param[in] mode sc_sha_mode_t. + \param[in] msg Pointer to the mac input message. + \param[in] msg_len Length of msg. + \param[out] out mac buffer, malloc by caller. + \param[out] out_len out mac length, + \return error code \ref csi_error_t +*/ +csi_error_t csi_hmac_calc(csi_hmac_t *mac, csi_sha_mode_t mode, uint8_t *msg, + uint32_t msg_len, uint8_t *out, uint32_t *out_len); +#ifdef __cplusplus +} +#endif + +#endif /* _SC_MAC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/i2s.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/i2s.h new file mode 100644 index 00000000000..f783d21d4b5 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/i2s.h @@ -0,0 +1,397 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/i2s.h + * @brief header file for i2s driver + * @version V1.0 + * @date 16. Mar 2020 + * @model i2s + ******************************************************************************/ + +#ifndef _DRV_I2S_H_ +#define _DRV_I2S_H_ + +#include +#include +#include +#include +#include "drv/ringbuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + I2S_MODE_MASTER, ///< I2s transmitter master mode + I2S_MODE_SLAVE, ///< I2s transmitter slave mode +} csi_i2s_mode_t; + +typedef enum { + I2S_PROTOCOL_I2S, ///< I2S protocol + I2S_PROTOCOL_MSB_JUSTIFIED, ///< MSB (left) justified protocol + I2S_PROTOCOL_LSB_JUSTIFIED, ///< LSB (right) justified protocol + I2S_PROTOCOL_PCM, ///< PCM protocol +} csi_i2s_protocol_t; + +typedef enum { + I2S_LEFT_POLARITY_LOW, ///< Low level represents the left channel + I2S_LEFT_POLARITY_HIGH, ///< High level represents the left channel +} csi_i2s_ws_left_polarity_t; + +typedef enum { + I2S_SAMPLE_RATE_8000 = 8000U, ///< I2S sample rate is 8000 + I2S_SAMPLE_RATE_11025 = 11025U, + I2S_SAMPLE_RATE_12000 = 12000U, + I2S_SAMPLE_RATE_16000 = 16000U, + I2S_SAMPLE_RATE_22050 = 22050U, + I2S_SAMPLE_RATE_24000 = 24000U, + I2S_SAMPLE_RATE_32000 = 32000U, + I2S_SAMPLE_RATE_44100 = 44100U, + I2S_SAMPLE_RATE_48000 = 48000U, + I2S_SAMPLE_RATE_96000 = 96000U, + I2S_SAMPLE_RATE_192000 = 192000U, + I2S_SAMPLE_RATE_256000 = 256000U, +} csi_i2s_sample_rate_t; + +typedef enum { + I2S_SAMPLE_WIDTH_16BIT = 16U, ///< I2S sample width is 16bit + I2S_SAMPLE_WIDTH_24BIT = 24U, + I2S_SAMPLE_WIDTH_32BIT = 32U, +} csi_i2s_sample_width_t; + +typedef enum { + I2S_SCLK_16FS = 16U, ///< SCLK frequency is 16 times that of I2S sample rate + I2S_SCLK_32FS = 32U, + I2S_SCLK_48FS = 48U, + I2S_SCLK_64FS = 64U, +} csi_i2s_sclk_freq_t; + +typedef enum { + I2S_MCLK_256FS = 256U, ///< MCLK frequency is 256 times that of I2S sample rate + I2S_MCLK_384FS = 384U, +} csi_i2s_mclk_freq_t; + +typedef struct { + csi_i2s_mode_t mode; ///< I2S work mode + csi_i2s_protocol_t protocol; ///< Protocols used by I2S + csi_i2s_ws_left_polarity_t polarity; ///< left channel polarity + csi_i2s_sample_rate_t rate; ///< I2S sample rate + csi_i2s_sample_width_t width; ///< I2S sample width + csi_i2s_sclk_freq_t sclk_nfs; ///< SCLK frequency is N times that of I2S sample rate + csi_i2s_mclk_freq_t mclk_nfs; ///< MCLK frequency is N times that of I2S sample rate +} csi_i2s_format_t; + +typedef enum { + I2S_LEFT_CHANNEL, + I2S_RIGHT_CHANNEL, + I2S_LEFT_RIGHT_CHANNEL, +} csi_i2s_sound_channel_t; + +typedef enum { + I2S_EVENT_SEND_COMPLETE, + I2S_EVENT_RECEIVE_COMPLETE, + I2S_EVENT_TX_BUFFER_EMPTY, + I2S_EVENT_RX_BUFFER_FULL, + I2S_EVENT_ERROR_OVERFLOW, + I2S_EVENT_ERROR_UNDERFLOW, + I2S_EVENT_ERROR, +} csi_i2s_event_t; + +typedef struct csi_i2s csi_i2s_t; + +struct csi_i2s { + csi_dev_t dev; ///< I2S hw-device info + void (*callback)(csi_i2s_t *i2s, csi_i2s_event_t event, void *arg); ///< I2S event callback for user + void *arg; ///< user private param passed to user callback + csi_ringbuf_t *tx_buf; ///< I2S send buffer + csi_ringbuf_t *rx_buf; ///< I2S receive buffer + csi_dma_ch_t *tx_dma; ///< send dma channel handle + csi_dma_ch_t *rx_dma; ///< receive dma channel handle + uint32_t tx_period; ///< I2S send period num data will callback + uint32_t rx_period; ///< I2S receive period num data will callback + csi_state_t state; ///< I2S communication state + void *priv; +}; + +/** + \brief Init i2s + \param[in] i2s I2s handle to operate + \param[in] idx I2s interface idx + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_init(csi_i2s_t *i2s, uint32_t idx); + +/** + \brief Uninit i2s + \param[in] i2s I2s handle to operate + \return none +*/ +void csi_i2s_uninit(csi_i2s_t *i2s); + +/** + \brief Enable i2s + \param[in] i2s I2s handle to operate + \param[in] en True enable, False disable + \return None +*/ +void csi_i2s_enable(csi_i2s_t *i2s, bool enable); + +/** + \brief I2s config format + \param[in] i2s I2s handle to operate + \param[in] format I2s config param \ref csi_i2s_format_t + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_format(csi_i2s_t *i2s, csi_i2s_format_t *format); + +/** + \brief Set the i2s tx mono + \param[in] i2s I2s handle to operate + \param[in] ch Mono channel selection + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_tx_select_sound_channel(csi_i2s_t *i2s, csi_i2s_sound_channel_t ch); + +/** + \brief Set the i2s rx mono + \param[in] i2s I2s handle to operate + \param[in] ch Mono channel selection + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_rx_select_sound_channel(csi_i2s_t *i2s, csi_i2s_sound_channel_t ch); + +/** + \brief Link DMA channel to i2s device + \param[in] i2s I2s handle to operate + \param[in] rx_dma The DMA channel for receive, when it is NULL means to unused dma + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_rx_link_dma(csi_i2s_t *i2s, csi_dma_ch_t *rx_dma); + +/** + \brief Link DMA channel to i2s device + \param[in] i2s I2s handle to operate + \param[in] tx_dma The DMA channel for send, when it is NULL means to unused dma + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_tx_link_dma(csi_i2s_t *i2s, csi_dma_ch_t *tx_dma); + +/** + \brief I2s rx buffer config + \param[in] i2s I2s handle to operate + \param[in] buffer I2s rx buffer + \return None +*/ +void csi_i2s_rx_set_buffer(csi_i2s_t *i2s, csi_ringbuf_t *buffer); + +/** + \brief I2s tx buffer config + \param[in] i2s I2s handle to operate + \param[in] buffer I2s tx buffer + \return None +*/ +void csi_i2s_tx_set_buffer(csi_i2s_t *i2s, csi_ringbuf_t *buffer); + +/** + \brief I2s rx set period.The value of period is to report a receive completion event + after each period value data is received + \param[in] i2s I2s handle to operate + \param[in] period I2s rx period + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_rx_set_period(csi_i2s_t *i2s, uint32_t period); + +/** + \brief I2s tx set period.The value of period is to report a receive completion event + after each period value data is send + \param[in] i2s I2s handle to operate + \param[in] period I2s tx period + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_tx_set_period(csi_i2s_t *i2s, uint32_t period); + +/** + \brief Get rx csi_ringbuf buffer free space + \param[in] i2s I2s handle to operate + \return Buffer free space (bytes) +*/ +uint32_t csi_i2s_rx_buffer_avail(csi_i2s_t *i2s); + +/** + \brief Get rx csi_ringbuf buffer used space + \param[in] i2s I2s handle to operate + \return Buffer used space (bytes) +*/ +uint32_t csi_i2s_rx_buffer_remain(csi_i2s_t *i2s); + +/** + \brief Reset the rx csi_ringbuf, discard all data in the buffer + \param[in] i2s I2s handle to operate + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_rx_buffer_reset(csi_i2s_t *i2s); + +/** + \brief Get tx csi_ringbuf buffer free space + \param[in] i2s I2s handle to operate + \return Buffer free space (bytes) +*/ +uint32_t csi_i2s_tx_buffer_avail(csi_i2s_t *i2s); + +/** + \brief Get tx csi_ringbuf buffer used space + \param[in] i2s I2s handle to operate + \return Buffer used space (bytes) +*/ +uint32_t csi_i2s_tx_buffer_remain(csi_i2s_t *i2s); + +/** + \brief Reset the tx csi_ringbuf, discard all data in the buffer + \param[in] i2s Handle to operate + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_tx_buffer_reset(csi_i2s_t *i2s); + +/** + \brief Send an amount of data to buffer in blocking mode + \param[in] i2s Operate handle + \param[in] data Pointer to send data buffer + \param[in] size Send data size + \return The num of data witch is send successful +*/ +int32_t csi_i2s_send(csi_i2s_t *i2s, const void *data, uint32_t size); + +/** + \brief Receive an amount of data to buffer in blocking mode + \param[in] i2s Operate handle + \param[out] data Pointer to receive data buffer + \param[in] size Receive data size + \return The size of data receive successfully +*/ +int32_t csi_i2s_receive(csi_i2s_t *i2s, void *data, uint32_t size); + +/** + \brief Write data to the buffer + With asynchronous sending + The data is first written to the buffer and then output through the i2s interface + Return value is the number of data that was successfully written to the buffer + \param[in] i2s Operate handle + \param[in] data Pointer to send data buffer + \param[in] size Send data size + \return The data size that write to buffer +*/ +uint32_t csi_i2s_send_async(csi_i2s_t *i2s, const void *data, uint32_t size); + +/** + \brief Read data from the buffer + Using asynchronous receive, i2s writes the received data to the buffer + This function reads data from the buffer, returns the number of successful reads + Returns 0 if there is no data in the buffer + \param[in] i2s Operate handle + \param[out] data Pointer to receive data buffer + \param[in] size Receive data size + \return The size of data read successfully +*/ +uint32_t csi_i2s_receive_async(csi_i2s_t *i2s, void *data, uint32_t size); + +/** + \brief Start i2s pause asynchronous send + \param[in] i2s Operate handle + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_send_pause(csi_i2s_t *i2s); + +/** + \brief Start i2s resume asynchronous send + \param[in] i2s Operate handle + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_send_resume(csi_i2s_t *i2s); + +/** + \brief Start i2s asynchronous send + \param[in] i2s Operate handle + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_send_start(csi_i2s_t *i2s); + +/** + \brief Start i2s asynchronous receive + \param[in] i2s Operate handle + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_receive_start(csi_i2s_t *i2s); + +/** + \brief Stop i2s asynchronous send + \param[in] i2s Operate handle + \return None +*/ +void csi_i2s_send_stop(csi_i2s_t *i2s); + +/** + \brief Stop i2s asynchronous receive + \param[in] i2s Operate handle + \return None +*/ +void csi_i2s_receive_stop(csi_i2s_t *i2s); + +/** + \brief Attach the callback handler to i2s + \param[in] i2s Operate handle + \param[in] cb Callback function + \param[in] arg User private param + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_attach_callback(csi_i2s_t *i2s, void *callback, void *arg); + +/** + \brief Detach the callback handler + \param[in] i2s Operate handle + \return None +*/ +void csi_i2s_detach_callback(csi_i2s_t *i2s); + +/** + \brief Get i2s status + \param[in] i2s I2s handle to operate + \param[out] state I2s state + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_get_state(csi_i2s_t *i2s, csi_state_t *state); + +/** + \brief Enable i2s power manage + \param[in] i2s I2s handle to operate + \return error code \ref csi_error_t +*/ +csi_error_t csi_i2s_enable_pm(csi_i2s_t *i2s); + +/** + \brief Disable i2s power manage + \param[in] i2s I2s handle to operate + \return None +*/ +void csi_i2s_disable_pm(csi_i2s_t *i2s); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_I2S_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/iic.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/iic.h new file mode 100644 index 00000000000..1759ac7566d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/iic.h @@ -0,0 +1,338 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file iic.h + * @brief header file for iic driver + * @version V1.0 + * @date 08. Apr 2020 + * @model iic + ******************************************************************************/ + +#ifndef _DRV_IIC_H_ +#define _DRV_IIC_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + \enum csi_iic_mode_t + \brief iic work in master/slave mode + */ +typedef enum { + IIC_MODE_MASTER = 0U, ///< IIC master + IIC_MODE_SLAVE ///< IIC slave +} csi_iic_mode_t; + +/** + \enum csi_iic_speed_t + \brief iic speed mode + */ +typedef enum { + IIC_BUS_SPEED_STANDARD = 0U, ///< Standard Speed (<=100kHz) + IIC_BUS_SPEED_FAST, ///< Fast Speed (<=400kHz) + IIC_BUS_SPEED_FAST_PLUS, ///< Fast plus Speed (<= 1MHz) + IIC_BUS_SPEED_HIGH ///< High Speed (<=3.4MHz) +} csi_iic_speed_t; + +/** + \enum csi_iic_address_mode_t + \brief iic address mode + */ +typedef enum { + IIC_ADDRESS_7BIT = 0U, ///< 7-bit address mode + IIC_ADDRESS_10BIT ///< 10-bit address mode +} csi_iic_addr_mode_t; + +/** + \enum csi_iic_mem_addr_size_t + \brief iic memory address size + */ +typedef enum { + IIC_MEM_ADDR_SIZE_8BIT = 0U, ///< IIC e2prom 8bit address mode + IIC_MEM_ADDR_SIZE_16BIT ///< IIC e2prom 16bit address mode +} csi_iic_mem_addr_size_t; + +/** + \enum csi_iic_event_t + \brief iic event signaled by iic driver + */ +typedef enum { + IIC_EVENT_SEND_COMPLETE = 0U, ///< Master/slave Send finished + IIC_EVENT_RECEIVE_COMPLETE, ///< Master/slave Receive finished + IIC_EVENT_ERROR_OVERFLOW, ///< Master/slave fifo overflow error + IIC_EVENT_ERROR_UNDERFLOW, ///< Master/slave fifo underflow error + IIC_EVENT_ERROR ///< The receive buffer was completely filled to FIFO and more data arrived. That data is lost +} csi_iic_event_t; + +/** + \struct csi_iic_t + \brief iic ctrl block + */ +typedef struct csi_iic csi_iic_t; +struct csi_iic { + csi_dev_t dev; ///< IIC hw-device info + void (*callback)(csi_iic_t *iic, csi_iic_event_t event, void *arg); ///< IIC event callback for user + void *arg; ///< User private param passed to user callback + uint8_t *data; ///< IIC transfer-data buffer + uint32_t size; ///< IIC transfer-data size + csi_iic_mode_t mode; ///< IIC mode + csi_dma_ch_t *tx_dma; ///< Send dma channel handle + csi_dma_ch_t *rx_dma; ///< Receive dma channel handle + void *send; ///< Send function pointer asynchronously + void *receive; ///< Receive function pointer asynchronously + csi_state_t state; ///< IIC current state + void *priv; +}; + +typedef void (*csi_iic_master_send_async_t)(csi_iic_t *iic, uint32_t devaddr, const void *data, uint32_t size); +typedef void (*csi_iic_master_receive_async_t)(csi_iic_t *iic, uint32_t devaddr, void *data, uint32_t size); +typedef void (*csi_iic_slave_send_async_t)(csi_iic_t *iic, const void *data, uint32_t size); +typedef void (*csi_iic_slave_receive_async_t)(csi_iic_t *iic, void *data, uint32_t size); + +/** + \brief Init iic ctrl block + Initializes the resources needed for the iic instance + \param[in] iic Handle of iic instance + \param[in] idx Index of instance + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_init(csi_iic_t *iic, uint32_t idx); + +/** + \brief Uninit iic ctrl block + Stops operation and releases the software resources used by the instance + \param[in] iic Handle of iic instance + \return None +*/ +void csi_iic_uninit(csi_iic_t *iic); + +/** + \brief Config iic master or slave mode + \param[in] iic Handle of iic instance + \param[in] mode iic mode \ref csi_iic_mode_t + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_mode(csi_iic_t *iic, csi_iic_mode_t mode); + +/** + \brief Config iic addr mode + \param[in] iic Handle of iic instance + \param[in] addr_mode iic addr mode \ref csi_iic_addr_mode_t + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_addr_mode(csi_iic_t *iic, csi_iic_addr_mode_t addr_mode); + +/** + \brief Config iic speed + \param[in] iic Handle of iic instance + \param[in] speed iic speed mode \ref csi_iic_speed_t + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_speed(csi_iic_t *iic, csi_iic_speed_t speed); + +/** + \brief Config iic own addr + \param[in] iic Handle of iic instance + \param[in] own_addr iic set own addr at slave mode + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_own_addr(csi_iic_t *iic, uint32_t own_addr); + +/** + \brief Start sending data as iic master + This function is blocking + \param[in] iic Handle of iic instance + \param[in] devaddr Addrress of slave device + \param[in] data Pointer to send data buffer + \param[in] size Size of data items to send + \param[in] timout Unit of time delay(ms) + \return The amount of real data sent or error code +*/ +int32_t csi_iic_master_send(csi_iic_t *iic, uint32_t devaddr, const void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start receiving data as iic master + This function is blocking + \param[in] iic Handle to operate + \param[in] devaddr iic addrress of slave device + \param[out] data Pointer to buffer for data to receive from iic receiver + \param[in] size Size of data items to receive + \param[in] timeout Unit of time delay(ms) + \return The amount of real data received or error code +*/ +int32_t csi_iic_master_receive(csi_iic_t *iic, uint32_t devaddr, void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start sending data as iic master + This function is non-blocking,\ref csi_iic_event_t is signaled when transfer completes or error happens + \param[in] iic Handle to operate + \param[in] devaddr iic addrress of slave device + \param[in] data Pointer to send data buffer + \param[in] size Size of data items to send + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_master_send_async(csi_iic_t *iic, uint32_t devaddr, const void *data, uint32_t size); + +/** + \brief Start receiving data as iic master. + This function is non-blocking.\ref csi_iic_event_t is signaled when transfer completes or error happens + \param[in] iic Handle to operate + \param[in] devaddr iic addrress of slave device + \param[out] data Pointer to buffer for data to receive from iic receiver + \param[in] size Size of data items to receive + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_master_receive_async(csi_iic_t *iic, uint32_t devaddr, void *data, uint32_t size); + +/** + \brief Start sending data as iic master + This function is blocking + \param[in] iic Handle of iic instance + \param[in] devaddr Addrress of slave device + \param[in] memaddr Internal addr of device + \param[in] memaddr_size Internal addr mode of device + \param[in] data Pointer to send data buffer + \param[in] size Size of data items to send + \param[in] timout Unit of time delay(ms) + \return The amount of real data sent or error code +*/ +int32_t csi_iic_mem_send(csi_iic_t *iic, uint32_t devaddr, uint16_t memaddr, csi_iic_mem_addr_size_t memaddr_size, const void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start receiving data as iic master + This function is blocking + \param[in] iic Handle to operate + \param[in] devaddr iic addrress of slave device + \param[in] memaddr Internal addr of device + \param[in] memaddr_mode Internal addr mode of device + \param[out] data Pointer to buffer for data to receive from eeprom device + \param[in] size Size of data items to receive + \param[in] timeout Unit of time delay(ms) + \return The amount of real data received or error code +*/ +int32_t csi_iic_mem_receive(csi_iic_t *iic, uint32_t devaddr, uint16_t memaddr, csi_iic_mem_addr_size_t memaddr_size, void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start sending data as iic slave + This function is blocking + \param[in] iic Handle to operate + \param[in] data Pointer to buffer with data to send to iic master + \param[in] size Size of data items to send + \param[in] timeout Unit of time delay(ms) + \return The amount of real data sent or error code +*/ +int32_t csi_iic_slave_send(csi_iic_t *iic, const void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start receiving data as iic slave + This function is blocking + \param[in] iic Handle to operate + \param[out] data Pointer to buffer for data to receive from iic master + \param[in] size Size of data items to receive + \param[in] timeout Unit of time delay(ms) + \return The amount of real data received or error code +*/ +int32_t csi_iic_slave_receive(csi_iic_t *iic, void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start sending data as iic slave + This function is non-blocking,\ref csi_iic_event_t is signaled when transfer completes or error happens + \param[in] iic Handle to operate + \param[in] data Pointer to buffer with data to send to iic master + \param[in] size Size of data items to send + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_slave_send_async(csi_iic_t *iic, const void *data, uint32_t size); + +/** + \brief Start receiving data as iic slave + This function is non-blocking,\ref csi_iic_event_t is signaled when transfer completes or error happens + \param[in] handle iic handle to operate + \param[out] data Pointer to buffer for data to receive from iic master + \param[in] size Size of data items to receive + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_slave_receive_async(csi_iic_t *iic, void *data, uint32_t size); + +/** + \brief Attach callback to the iic + \param[in] iic iic handle to operate + \param[in] cb Event callback function \ref csi_iic_callback_t + \param[in] arg User private param for event callback + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_attach_callback(csi_iic_t *iic, void *callback, void *arg); + +/** + \brief Detach callback from the iic + \param[in] iic iic handle to operate + \return None +*/ +void csi_iic_detach_callback(csi_iic_t *iic); + +/** + \brief Config iic stop to generate + \param[in] iic iic handle to operate + \param[in] enable Transfer operation is pending - stop condition will not be generated + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_xfer_pending(csi_iic_t *iic, bool enable); + +/** + \brief Link DMA channel to iic device + \param[in] iic Handle to operate + \param[in] tx_dma The DMA channel handle for send, when it is NULL means to unlink the channel + \param[in] rx_dma The DMA channel handle for receive, when it is NULL means to unlink the channel + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_link_dma(csi_iic_t *iic, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma); + +/** + \brief Get iic state + \param[in] iic Handle to operate + \param[out] state iic state \ref csi_state_t + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_get_state(csi_iic_t *iic, csi_state_t *state); + +/** + \brief Enable iic power manage + \param[in] iic iic handle to operate + \return error code \ref csi_error_t +*/ +csi_error_t csi_iic_enable_pm(csi_iic_t *iic); + +/** + \brief Disable iic power manage + \param[in] iic iic handle to operate + \return None +*/ +void csi_iic_disable_pm(csi_iic_t *iic); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_IIC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/intc.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/intc.h new file mode 100644 index 00000000000..573f33eb5ca --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/intc.h @@ -0,0 +1,178 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/intc.h + * @brief Header File for INTC Driver + * @version V1.0 + * @date 02. June 2020 + * @model intc + ******************************************************************************/ + +#ifndef _DRV_INTC_H_ +#define _DRV_INTC_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +typedef enum int_trigger_mode_t { + INT_MODE_LOW_LEVEL, + INT_MODE_HIGH_LEVEL, + INT_MODE_RISING_EDGE, + INT_MODE_FALLING_EDGE, + INT_MODE_DOUBLE_EDGE, +} int_trigger_mode_t; + +/** + \brief Initialize the INTC interrupt controller + */ +void csi_intc_init(void); + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the INTC interrupt controller. + \param[in] IRQn External interrupt number. Value cannot be negative. + */ +void csi_intc_enable_irq(int32_t IRQn); + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the INTC interrupt controller. + \param[in] IRQn External interrupt number. Value cannot be negative. + */ +void csi_intc_disable_irq(int32_t IRQn); + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the INTC and returns the pending bit for the specified interrupt. + \param[in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +uint32_t csi_intc_get_pending_irq(int32_t IRQn); + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param[in] IRQn Interrupt number. Value cannot be negative. + */ +void csi_intc_set_pending_irq(int32_t IRQn); + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param[in] IRQn External interrupt number. Value cannot be negative. + */ +void csi_intc_clear_pending_irq(int32_t IRQn); + +/** + \brief Get Wake up Interrupt + \details Reads the wake up register in the INTC and returns the pending bit for the specified interrupt. + \param[in] IRQn Interrupt number. + \return 0 Interrupt is not set as wake up interrupt. + \return 1 Interrupt is set as wake up interrupt. + */ +uint32_t csi_intc_get_wakeup_irq(int32_t IRQn); + +/** + \brief Set Wake up Interrupt + \details Sets the wake up bit of an external interrupt. + \param[in] IRQn Interrupt number. Value cannot be negative. + */ +void csi_intc_set_wakeup_irq(int32_t IRQn); + +/** + \brief Clear Wake up Interrupt + \details Clears the wake up bit of an external interrupt. + \param[in] IRQn External interrupt number. Value cannot be negative. + */ +void csi_intc_clear_wakeup_irq(int32_t IRQn); + +/** + \brief Get Active Interrupt + \details Reads the active register in the INTC and returns the active bit for the device specific interrupt. + \param[in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +uint32_t csi_intc_get_active(int32_t IRQn); + +/** + \brief Set Threshold register + \details set the threshold register in the INTC. + \param[in] VectThreshold specific vecter threshold. + \param[in] PrioThreshold specific priority threshold. + */ +void csi_intc_set_threshold(uint32_t VectThreshold, uint32_t PrioThreshold); + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param[in] IRQn Interrupt number. + \param[in] priority Priority to set. + */ +void csi_intc_set_prio(int32_t IRQn, uint32_t priority); + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param[in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +uint32_t csi_intc_get_prio(int32_t IRQn); + +/** + \brief funciton is acknowledge the IRQ. this interface is internally used by irq system + \param[in] irq irq number to operate + \return 0 on success; -1 on failure + */ +int csi_intc_ack_irq(int32_t IRQn); + +/** + \brief This function is set the attributes of an IRQ. + \param[in] irq irq number to operate + \param[in] priority interrupt priority + \param[in] trigger_mode interrupt trigger_mode + \return 0 on success; -1 on failure +*/ +int csi_intc_set_attribute(int32_t IRQn, uint32_t priority, int_trigger_mode_t trigger_mode); + +/** + \brief Set interrupt handler + \details Set the interrupt handler according to the interrupt num, the handler will be filled in g_irqvector[]. + \param[in] IRQn Interrupt number. + \param[in] handler Interrupt handler. + */ +void csi_intc_set_vector(int32_t IRQn, uint32_t handler); + +/** + \brief Get interrupt handler + \details Get the address of interrupt handler function. + \param[in] IRQn Interrupt number. + */ +uint32_t csi_intc_get_vector(int32_t IRQn); + +#endif /* _DRV_INTC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/io.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/io.h new file mode 100644 index 00000000000..5b970c33c0b --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/io.h @@ -0,0 +1,131 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/io.h + * @brief Header File for register bits operation + * @version V1.0 + * @date 9. Oct 2020 + * @model io + ******************************************************************************/ + +#ifndef _DRV_IO_H_ +#define _DRV_IO_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Bit field operate*/ +#define REG64(addr) (*(volatile uint64_t *)(addr)) +#define REG32(addr) (*(volatile uint32_t *)(addr)) +#define REG16(addr) (*(volatile uint16_t *)(addr)) +#define REG8(addr) (*(volatile uint8_t *)(addr)) + +/* Insert value to some field in reg, other field is set to 0(the field make macro) */ +#define HAL_FMK(PER_REG_FIELD, val) \ + (((val) << PER_REG_FIELD##_SHIFT) & PER_REG_FIELD##_MASK) + +/* Get value of some field in reg(the field extract macro) */ +#define HAL_FEXT(reg, PER_REG_FIELD) \ + (((reg) & PER_REG_FIELD##_MASK) >> PER_REG_FIELD##_SHIFT) + +/* Insert value to some field in reg, other field don't change(the field insert macro) */ +#define HAL_FINS(reg, PER_REG_FIELD, val) \ + ((reg) = ((reg) & ~PER_REG_FIELD##_MASK) \ + | HAL_FMK(PER_REG_FIELD, val)) + + +/* Bit operate */ +/* Set one value to 1, other bit don't change*/ +#define HAL_BIT_SET(reg, bit) ((reg) = ((reg) | (1U << (bit)))) + +/* Set one value to 0, other bit don't change*/ +#define HAL_BIT_CLR(reg, bit) ((reg) = ((reg) & (~(1U << (bit))))) + +/* Get value of one bit(0/1) */ +#define HAL_GET_BIT_VAL(reg, bit) (((reg)>> (bit)) & 1U) + +/* Judge one bit is 1 or not */ +#define HAL_IS_BIT_SET(reg, pos) (((reg) & (1U << (pos))) != 0x0U) + +/* Judge one bit is 0 or not */ +#define HAL_IS_BIT_CLR(reg, pos) (((reg) & (1U << (pos))) == 0x0U) + +/* Set one value to bit, other bit don't change*/ +#define HAL_BIT_INSR(reg, bit, val) \ + ((reg) = (((reg) & (~(1U << (bit)))) | (((val) & 1U) << (bit)))) + + +static inline uint8_t getreg8(volatile void *addr) +{ + return *(volatile uint8_t *)addr; +} + +static inline void putreg8(uint8_t val, volatile void *addr) +{ + *(volatile uint8_t *)addr = val; +} + +static inline uint16_t getreg16(volatile void *addr) +{ + return *(volatile uint16_t *)addr; +} + +static inline void putreg16(uint16_t val, volatile void *addr) +{ + *(volatile uint16_t *)addr = val; +} + +static inline uint32_t getreg32(volatile void *addr) +{ + return *(volatile uint32_t *)addr; +} + +static inline void putreg32(uint32_t val, volatile void *addr) +{ + *(volatile uint32_t *)addr = val; +} + +static inline uint64_t getreg64(volatile void *addr) +{ + return *(volatile uint64_t *)addr; +} + +static inline void putreg64(uint32_t val, volatile void *addr) +{ + *(volatile uint64_t *)addr = val; +} + +static inline uint32_t inl(void *addr) +{ + return *(volatile uint32_t *)addr; +} + +static inline void outl(uint32_t val, void *addr) +{ + *(volatile uint32_t *)addr = val; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_IO_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/irq.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/irq.h new file mode 100644 index 00000000000..2e1a2bae899 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/irq.h @@ -0,0 +1,149 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/irq.h + * @brief header File for IRQ Driver + * @version V1.0 + * @date 16. Mar 2020 + * @model irq + ******************************************************************************/ + +#ifndef _DRV_IRQ_H_ +#define _DRV_IRQ_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + \brief Enable irq. + \param[in] irq_num Number of IRQ. + \return None. +*/ +__ALWAYS_STATIC_INLINE void csi_irq_enable(uint32_t irq_num) +{ + extern void soc_irq_enable(uint32_t irq_num); + soc_irq_enable(irq_num); +} + +/** + \brief Disable irq. + \param[in] irq_num Number of IRQ. + \return None. +*/ +__ALWAYS_STATIC_INLINE void csi_irq_disable(uint32_t irq_num) +{ + extern void soc_irq_disable(uint32_t irq_num); + soc_irq_disable(irq_num); +} + +/** + \brief Attach irq handler. + \param[in] irq_num Number of IRQ. + \param[in] irq_handler IRQ Handler. + \param[in] dev The dev to operate + \return None. +*/ +void csi_irq_attach(uint32_t irq_num, void *irq_handler, csi_dev_t *dev); + +/** + \brief Attach irq handler2 for compatible. + \param[in] irq_num Number of IRQ. + \param[in] irq_handler2 IRQ Handler. + \param[in] dev The dev to operate + \param[in] arg user data of irq_handler2 + \return None. +*/ +void csi_irq_attach2(uint32_t irq_num, void *irq_handler2, csi_dev_t *dev, void *arg); + +/** + \brief detach irq handler. + \param[in] irq_num Number of IRQ. + \param[in] irq_handler IRQ Handler. + \return None. +*/ +void csi_irq_detach(uint32_t irq_num); + +/** + \brief Set irq priority + \param[in] irq_num Number of IRQ. + \param[in] priority IRQ Priority. + \return None. +*/ +__ALWAYS_STATIC_INLINE void csi_irq_priority(uint32_t irq_num, uint32_t priority) +{ + extern void soc_irq_priority(uint32_t irq_num, uint32_t priority); + soc_irq_priority(irq_num, priority); +} + +/** + \brief Gets whether the interrupt is enabled + \param[in] irq_num Number of IRQ. + \return true or false. +*/ +static inline bool csi_irq_is_enabled(uint32_t irq_num) +{ + extern bool soc_irq_is_enabled(uint32_t irq_num); + return soc_irq_is_enabled(irq_num); +} + +/** + \brief Enable the interrupt wakeup attribution + \param[in] irq_num Number of IRQ. + \return None. +*/ +__ALWAYS_STATIC_INLINE void csi_irq_enable_wakeup(uint32_t irq_num) +{ + extern void soc_irq_enable_wakeup(uint32_t irq_num); + soc_irq_enable_wakeup(irq_num); +} + +/** + \brief Disable the interrupt wakeup attribution + \param[in] irq_num Number of IRQ. + \return None. +*/ +__ALWAYS_STATIC_INLINE void csi_irq_disable_wakeup(uint32_t irq_num) +{ + extern void soc_irq_disable_wakeup(uint32_t irq_num); + soc_irq_disable_wakeup(irq_num); +} + +/** + \brief Gets whether in irq context + \return true or false. +*/ +bool csi_irq_context(void); + +/** + \brief Dispatching irq handlers + \return None. +*/ +void do_irq(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_IRQ_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/iso7816.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/iso7816.h new file mode 100644 index 00000000000..706d4fa60bd --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/iso7816.h @@ -0,0 +1,409 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/iso7816.h + * @brief Header File for ISO7816 Driver + * @version V1.0 + * @date 9. Oct 2020 + * @model iso7816 + ******************************************************************************/ + +#ifndef _DRV_ISO7816_H_ +#define _DRV_ISO7816_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + A_5V, + B_3_3V, + C_1_8V, +} dcd_vclass_t; + +typedef enum { + T0, + T1, +} iso7816_tprotocol_t; + +typedef enum { + ISO7816_EVENT_CARD_DETECTED, + ISO7816_EVENT_READ_COMPLETE, + ISO7816_EVENT_WRITE_COMPLETE, + ISO7816_EVENT_READ_ERROR, + ISO7816_EVENT_WRITE_ERROR, + ISO7816_EVENT_ACTIVATE_SUCCESS, + ISO7816_EVENT_ACTIVATE_FAILED, + ISO7816_EVENT_CARD_ERROR_DEACTIVATE, + ISO7816_EVENT_CARD_SESSION_CLOSED, + ISO7816_EVENT_RX_FULL, + ISO7816_EVENT_CWT_TIME_OUT, + ISO7816_EVENT_RX_OVER, + ISO7816_EVENT_CRC_ERR, + ISO7816_EVENT_PARITY_ERR, + ISO7816_EVENT_SLAVE_ATR_DETECTED, + ISO7816_EVENT_SLAVE_ATR_DONE, +} iso7816_event_t; + +typedef void (*iso7816_event_cb_t)(iso7816_event_t event, void *arg); + +typedef enum { + ISO7816_SLAVE, + ISO7816_MASTER, +} iso7816_mode_t; + +typedef struct { + uint8_t clk_div; + dcd_vclass_t vclass; + iso7816_mode_t mode; + int32_t card_detected_en; +} iso7816_config_t; + +typedef enum { + ISO7816_A_ONLY = 1U, + ISO7816_B_ONLY, + ISO7816_C_ONLY, + ISO7816_AB, + ISO7816_AC, + ISO7816_BC, + ISO7816_ABC, +} iso7816_voltage_class_t; + +typedef struct { + iso7816_voltage_class_t support_voltage_class; + int32_t proto_t; + int32_t clk_stop_is_support; + int32_t history_byte_num; + uint8_t history_data[15]; +} iso7816_atr_info_t; + +typedef enum { + EVEN_PARITY, + ODD_PARITY, +} iso7816_parity_type_t; + +typedef enum { + ISO7816_DRIECT, + ISO7816_INVERSE, +} iso7816_convention_t; + +typedef enum { + INVCTIVE, + ACTIVATEING, + PSS_TRF, + PSS_RECV, + ACTIVATE, +} iso7816_card_sta_t; + +/** + \brief Initialize ISO7816 master interface + \param[in] idx Master index + \param[in] cb_event Pointer to \ref iso7816_event_cb_t + \param[in] cb_arg Event callback arg + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_init(int idx, iso7816_event_cb_t cb_event, void *cb_arg); + +/** + \brief Uninit ISO7816 master interface + \param[in] idx Master index + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_uninit(int idx); + +/** + \brief Config ISO7816 master attributes + \param[in] idx Master index + \param[in] config master config \ref iso7816_config_t + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_config(int idx, iso7816_config_t *config); + +/** + \brief Receiving data from ISO7816 master receiver, used polling mode + \param[in] idx Master index + \param[in] buf Pointer to buffer for data to receive from i2s receiver + \param[in] len Size of receiver data + \param[in] time_out Receive time out value + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_receive(int idx, uint8_t *buf, uint32_t len, uint32_t time_out); + +/** + \brief Receiving data from ISO7816 master receiver, used interrupt mode + \param[in] idx Master index + \param[in] buf Pointer to buffer for data to receive from i2s receiver + \param[in] len Size of receiver data + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_receive_it(int idx, uint8_t *buf, uint32_t len); + +/** + \brief Sending data to ISO7816 master transmitter, used polling mode + \param[in] idx Master index + \param[in] buf Pointer to buffer for data to send + \param[in] len Size of tranmitter data + \param[in] time_out Send time out value + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_send(int idx, uint8_t *buf, uint32_t len, uint32_t time_out); + +/** + \brief Sending data to ISO7816 master transmitter, used interrupt mode + \param[in] idx Master index + \param[in] buf Pointer to buffer for data to send + \param[in] len Size of tranmitter data + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_send_it(int idx, uint8_t *buf, uint32_t len); + +/** + \brief ISO7816 master performs the activation smart card process, this process + is non-blocking,should monitor callback event or read card status to check card is activate + \param[in] idx Master index + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_card_activate(int idx); + +/** + \brief ISO7816 master performs the deactivation smart card process, this process + is non-blocking,should monitor callback event or read card status to check card is activate + \param[in] idx Master index + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_card_deactivate(int idx); + +/** + \brief The smard card session status + \param[in] idx Master index + \return smart card status. +*/ +iso7816_card_sta_t csi_iso7816_master_card_status(int idx); + +/** + \brief ISO7816 master performs the warm reset smart card process + \param[in] idx Master index + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_card_warm_reset(int idx); + +/** + \brief ISO7816 master performs clock stop + \param[in] idx Master index + \param[in] en The clk last state when power down + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_card_clk_stop_enable(int idx, int en); + +/** + \brief ISO7816 master performs pwoer down + \param[in] idx Master index + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_power_down(int idx); + +/** + \brief Get atr analytical results + \param[in] idx Master index + \param[out] info The result of atr information + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_master_atr_info(int idx, iso7816_atr_info_t *info); + +/** + \brief Initialize ISO7816 slave interface + \param[in] idx Slave index + \param[in] cb Pointer to \ref iso7816_event_cb_t + \param[in] cb_arg Event callback arg + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_init(int idx, iso7816_event_cb_t cb, void *cb_arg); + +/** + \brief Uninit ISO7816 slave interface + \param[in] idx Slave index + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_uninit(int idx); + +/** + \brief Enable ISO7816 slave interface + \param[in] idx Slave index + \param[in] en Slave enable + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_enable(int idx, int en); + +/** + \brief Enable ISO7816 slave receive parity + \param[in] idx Slave index + \param[in] en Enable receive parity + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_receive_parity_enable(int idx, int en); + +/** + \brief Set ISO7816 slave receive parity attributes + \param[in] idx Slave index + \param[in] type Set receiver parity type + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_set_receive_parity(int idx, iso7816_parity_type_t type); + +/** + \brief Enable ISO7816 slave send parity + \param[in] idx Slave index + \param[in] en Enable send parity + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_send_parity_enable(int idx, int en); + +/** + \brief Set ISO7816 slave send parity attributes + \param[in] idx Slave index + \param[in] type Set send parity attributes + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_set_send_parity(int idx, iso7816_parity_type_t type); + +/** + \brief Set the number of ISO7816 slave receive retry + \param[in] idx Slave index + \param[in] val Set the number retry + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_set_receive_retry(int idx, uint8_t val); + +/** + \brief Set the number of ISO7816 send send retry + \param[in] idx Slave index + \param[in] val Set the number retry + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_set_send_retry(int idx, uint8_t val); + +/** + \brief Set the ISO7816 slave GT + \param[in] idx Slave index + \param[in] val Set the slave GT + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_set_gt(int idx, uint8_t val); + +/** + \brief Set the ISO7816 slave WT + \param[in] idx Slave index + \param[in] val Set the slave WT + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_set_wt(int idx, uint16_t val); + +/** + \brief Set the ISO7816 slave baud, baud = F/D + \param[in] idx Slave index + \param[in] val Set the slave baud + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_set_baud(int idx, uint16_t val); + +/** + \brief Set the ISO7816 slave convention + \param[in] idx Slave index + \param[in] convention Set the slave convention \ref iso7816_convention_t + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_set_convention(int idx, iso7816_convention_t convention); + +/** + \brief Set the ISO7816 slave art response time, val range is 400~40000 + \param[in] idx Slave index + \param[in] val Set the slave art response time + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_set_atr_ack_time(int idx, int val); + +/** + \brief Set the ISO7816 slave send atr data + \param[in] idx Slave index + \param[in] buf Pointer to buffer for data to send + \param[in] len Size of tranmitter data + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_send_atr(int idx, uint8_t *buf, int len); + +/** + \brief Receiving data from ISO7816 slave receiver, used polling mode + \param[in] idx Master index + \param[in] buf Pointer to buffer for data to receive from i2s receiver + \param[in] len Size of receiver data + \param[in] timer_out receive time out value + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_receive(int idx, uint8_t *buf, uint32_t len, uint32_t time_out); + +/** + \brief Flushed the ISO7816 slave receive fifo + \param[in] idx Master index + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_flushed_receive_fifo(int idx); + +/** + \brief Receiving data from ISO7816 slave receiver, used interrupt mode + \param[in] idx Master index + \param[in] buf Pointer to buffer for data to receive from i2s receiver + \param[in] len Size of receiver data + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_receive_it(int idx, uint8_t *buf, uint32_t len); + +/** + \brief Sending data to ISO7816 slave transmitter, used polling mode + \param[in] idx Slave index + \param[in] buf Pointer to buffer for data to send + \param[in] len Size of tranmitter data + \param[in] timer_out Send time out value + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_send(int idx, uint8_t *buf, uint32_t len, uint32_t time_out); + +/** + \brief Flushed the ISO7816 slave send fifo. + \param[in] idx Master index + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_flushed_send_fifo(int idx); + +/** + \brief Sending data to ISO7816 slave transmitter, used interrupt mode + \param[in] idx Slave index + \param[in] buf Pointer to buffer for data to send + \param[in] len Size of tranmitter data + \return 0 for success, negative for error code +*/ +int32_t csi_iso7816_slave_send_it(int idx, uint8_t *buf, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_ISO7816_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/list.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/list.h new file mode 100644 index 00000000000..9f65050cbce --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/list.h @@ -0,0 +1,350 @@ +#ifndef AOS_LIST_H +#define AOS_LIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Get offset of a member variable. + * + * @param[in] type the type of the struct this is embedded in. + * @param[in] member the name of the variable within the struct. + */ +#define aos_offsetof(type, member) ((size_t)&(((type *)0)->member)) + +/* + * Get the struct for this entry. + * + * @param[in] ptr the list head to take the element from. + * @param[in] type the type of the struct this is embedded in. + * @param[in] member the name of the variable within the struct. + */ +#define aos_container_of(ptr, type, member) \ + ((type *) ((char *) (ptr) - aos_offsetof(type, member))) + +/* for double link list */ +typedef struct dlist_s { + struct dlist_s *prev; + struct dlist_s *next; +} dlist_t; + +static inline void __dlist_add(dlist_t *node, dlist_t *prev, dlist_t *next) +{ + node->next = next; + node->prev = prev; + + prev->next = node; + next->prev = node; +} + +/* + * Get the struct for this entry. + * + * @param[in] addr the list head to take the element from. + * @param[in] type the type of the struct this is embedded in. + * @param[in] member the name of the dlist_t within the struct. + */ +#define dlist_entry(addr, type, member) \ + ((type *)((long)addr - aos_offsetof(type, member))) + + +static inline void dlist_add(dlist_t *node, dlist_t *queue) +{ + __dlist_add(node, queue, queue->next); +} + +static inline void dlist_add_tail(dlist_t *node, dlist_t *queue) +{ + __dlist_add(node, queue->prev, queue); +} + +static inline void dlist_del(dlist_t *node) +{ + dlist_t *prev = node->prev; + dlist_t *next = node->next; + + prev->next = next; + next->prev = prev; +} + +static inline void dlist_init(dlist_t *node) +{ + node->next = node->prev = node; +} + +static inline void INIT_AOS_DLIST_HEAD(dlist_t *list) +{ + list->next = list; + list->prev = list; +} + +static inline int dlist_empty(const dlist_t *head) +{ + return head->next == head; +} + +/* + * Initialise the list. + * + * @param[in] list the list to be inited. + */ +#define AOS_DLIST_INIT(list) {&(list), &(list)} + +/* + * Get the first element from a list + * + * @param[in] ptr the list head to take the element from. + * @param[in] type the type of the struct this is embedded in. + * @param[in] member the name of the dlist_t within the struct. + */ +#define dlist_first_entry(ptr, type, member) \ + dlist_entry((ptr)->next, type, member) + +/* + * Iterate over a list. + * + * @param[in] pos the &struct dlist_t to use as a loop cursor. + * @param[in] head he head for your list. + */ +#define dlist_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/* + * Iterate over a list safe against removal of list entry. + * + * @param[in] pos the &struct dlist_t to use as a loop cursor. + * @param[in] n another &struct dlist_t to use as temporary storage. + * @param[in] head he head for your list. + */ +#define dlist_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/* + * Iterate over list of given type. + * + * @param[in] queue he head for your list. + * @param[in] node the &struct dlist_t to use as a loop cursor. + * @param[in] type the type of the struct this is embedded in. + * @param[in] member the name of the dlist_t within the struct. + */ +#define dlist_for_each_entry(queue, node, type, member) \ + for (node = aos_container_of((queue)->next, type, member); \ + &node->member != (queue); \ + node = aos_container_of(node->member.next, type, member)) + +/* + * Iterate over list of given type safe against removal of list entry. + * + * @param[in] queue the head for your list. + * @param[in] n the type * to use as a temp. + * @param[in] node the type * to use as a loop cursor. + * @param[in] type the type of the struct this is embedded in. + * @param[in] member the name of the dlist_t within the struct. + */ +#define dlist_for_each_entry_safe(queue, n, node, type, member) \ + for (node = aos_container_of((queue)->next, type, member), \ + n = (queue)->next ? (queue)->next->next : NULL; \ + &node->member != (queue); \ + node = aos_container_of(n, type, member), n = n ? n->next : NULL) + +/* + * Get the struct for this entry. + * @param[in] ptr the list head to take the element from. + * @param[in] type the type of the struct this is embedded in. + * @param[in] member the name of the variable within the struct. + */ +#define list_entry(ptr, type, member) \ + aos_container_of(ptr, type, member) + + +/* + * Iterate backwards over list of given type. + * + * @param[in] pos the type * to use as a loop cursor. + * @param[in] head he head for your list. + * @param[in] member the name of the dlist_t within the struct. + * @param[in] type the type of the struct this is embedded in. + */ +#define dlist_for_each_entry_reverse(pos, head, member, type) \ + for (pos = list_entry((head)->prev, type, member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, type, member)) + + +/* + * Get the list length. + * + * @param[in] queue the head for your list. + */ +int dlist_entry_number(dlist_t *queue); + + + +/* + * Initialise the list. + * + * @param[in] name the list to be initialized. + */ +#define AOS_DLIST_HEAD_INIT(name) { &(name), &(name) } + +/* + * Initialise the list. + * + * @param[in] name the list to be initialized. + */ +#define AOS_DLIST_HEAD(name) \ + dlist_t name = AOS_DLIST_HEAD_INIT(name) + +/* for single link list */ +typedef struct slist_s { + struct slist_s *next; +} slist_t; + +static inline void slist_add(slist_t *node, slist_t *head) +{ + node->next = head->next; + head->next = node; +} + +void slist_add_tail(slist_t *node, slist_t *head); + +static inline void slist_del(slist_t *node, slist_t *head) +{ + while (head->next) { + if (head->next == node) { + head->next = node->next; + break; + } + + head = head->next; + } +} + +static inline int slist_empty(const slist_t *head) +{ + return !head->next; +} + +static inline void slist_init(slist_t *head) +{ + head->next = 0; +} + +static inline slist_t *slist_remove(slist_t *l, slist_t *n) +{ + /* remove slist head */ + struct slist_s *node = l; + while (node->next && node->next != n) node = node->next; + + /* remove node */ + if (node->next != (slist_t *)0) node->next = node->next->next; + + return l; +} + +static inline slist_t *slist_first(slist_t *l) +{ + return l->next; +} + +static inline slist_t *slist_tail(slist_t *l) +{ + while (l->next) l = l->next; + + return l; +} + +static inline slist_t *slist_next(slist_t *n) +{ + return n->next; +} + +/* +* Iterate over list of given type. +* +* @param[in] queue he head for your list. +* @param[in] node the type * to use as a loop cursor. +* @param[in] type the type of the struct this is embedded in. +* @param[in] member the name of the slist_t within the struct. +*/ +#define slist_for_each_entry(queue, node, type, member) \ + for (node = (queue)->next? aos_container_of((queue)->next, type, member) : NULL; \ + node; \ + node = node->member.next ? aos_container_of(node->member.next, type, member) : NULL) + +/* + * Iterate over list of given type safe against removal of list entry. + * + * @param[in] queue the head for your list. + * @param[in] tmp the type * to use as a temp. + * @param[in] node the type * to use as a loop cursor. + * @param[in] type the type of the struct this is embedded in. + * @param[in] member the name of the slist_t within the struct. + */ +#define slist_for_each_entry_safe(queue, tmp, node, type, member) \ + for (node = (queue)->next? aos_container_of((queue)->next, type, member) : NULL, \ + tmp = (queue)->next ? (queue)->next->next : NULL; \ + node; \ + node = tmp ? aos_container_of(tmp, type, member) : NULL, tmp = tmp ? tmp->next : NULL) + +/* + * Initialise the list. + * + * @param[in] name the list to be initialized. + */ +#define AOS_SLIST_HEAD_INIT(name) {0} + +/* + * Initialise the list. + * + * @param[in] name the list to be initialized. + */ +#define AOS_SLIST_HEAD(name) \ + slist_t name = AOS_SLIST_HEAD_INIT(name) + +/* + * Get the struct for this entry. + * @param[in] addr the list head to take the element from. + * @param[in] type the type of the struct this is embedded in. + * @param[in] member the name of the slist_t within the struct. + */ +#define slist_entry(addr, type, member) ( \ + addr ? (type *)((long)addr - aos_offsetof(type, member)) : (type *)addr \ +) + +/* +* Get the first element from a list. +* +* @param[in] ptr the list head to take the element from. +* @param[in] type the type of the struct this is embedded in. +* @param[in] member the name of the slist_t within the struct. +*/ +#define slist_first_entry(ptr, type, member) \ + slist_entry((ptr)->next, type, member) + +/** + * slist_tail_entry - get the tail element from a slist + * @ptr: the slist head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the slist_struct within the struct. + * + * Note, that slist is expected to be not empty. + */ +#define slist_tail_entry(ptr, type, member) \ + slist_entry(slist_tail(ptr), type, member) + +/* + * Get the list length. + * + * @param[in] queue the head for your list. + */ +int slist_entry_number(slist_t *queue); + +#ifdef __cplusplus +} +#endif + +#endif /* AOS_LIST_H */ + diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/mbox.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/mbox.h new file mode 100644 index 00000000000..c5090425c6d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/mbox.h @@ -0,0 +1,104 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/mbox.h + * @brief Header File for MBOX Driver + * @version V1.0 + * @date 5. Apr 2020 + * @model mbox + ******************************************************************************/ + +#ifndef _DRV_MBOX_H_ +#define _DRV_MBOX_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + MBOX_EVENT_SEND_COMPLETE = 0U, ///< Send completed; however mbox may still transmit data + MBOX_EVENT_RECEIVED = 1U, ///< Data Received, only in mbox buf, call memcpy() get the data + MBOX_EVENT_ERROR = 2U, ///< Mbox transmit error occurred +} csi_mbox_event_t; + +typedef struct csi_mbox csi_mbox_t; +struct csi_mbox { + csi_dev_t dev; + void (*callback)(csi_mbox_t *mbox, csi_mbox_event_t event, uint32_t channel_id, uint32_t received_len, void *arg); + void *arg; + void *priv; +}; + +/** + \brief Initialize mbox Interface. + Initializes the resources needed for the mbox interface. + \param[in] mbox Operate handle. + \param[in] idx The device idx. + \return Error code \ref csi_error_t. +*/ +csi_error_t csi_mbox_init(csi_mbox_t *mbox, uint32_t idx); + +/** + \brief Uninitialize mbox interface. stops operation and releases the software resources used by the interface. + \param[in] mbox Operate handle. +*/ +void csi_mbox_uninit(csi_mbox_t *mbox); + +/** + \brief Start sending data to mbox transmitter. + \param[in] mbox Operate handle. + \param[in] channel_id Index of channel. + \param[in] data Pointer to buffer with data to send to mbox transmitter. + \param[in] size Number of data items to send. + \return sent Number of data or error code. +*/ +int32_t csi_mbox_send(csi_mbox_t *mbox, uint32_t channel_id, const void *data, uint32_t size); + +/** + \brief Start receiving data from mbox receiver. + \param[in] mbox Operate handle. + \param[in] channel_id Index of channel. + \param[out] data Pointer to buffer with data to receive from mailbox. + \param[in] size Number of data items to receive. + \return received Number or error code. +*/ +int32_t csi_mbox_receive(csi_mbox_t *mbox, uint32_t channel_id, void *data, uint32_t size); + +/** + \brief Attach callback to the mbox. + \param[in] mbox Operate handle. + \param[in] cb Event callback function. + \param[in] arg User private param for event callback. + \return Error code \ref csi_error_t. +*/ +csi_error_t csi_mbox_attach_callback(csi_mbox_t *mbox, void *callback, void *arg); + +/** + \brief Detach callback from the mbox + \param[in] mbox Operate handle. +*/ +void csi_mbox_detach_callback(csi_mbox_t *mbox); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_MBOX_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pin.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pin.h new file mode 100644 index 00000000000..3bc07ba0639 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pin.h @@ -0,0 +1,197 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file soc.h + * @brief For pin + * @version V1.0 + * @date 11. Mar 2020 + ******************************************************************************/ + +#ifndef _DRV_PIN_H_ +#define _DRV_PIN_H_ + +#include +#include +#include + +typedef csi_gpio_mode_t csi_pin_mode_t; + +typedef enum { + PIN_SPEED_LV0 = 0U, + PIN_SPEED_LV1, + PIN_SPEED_LV2, + PIN_SPEED_LV3 +} csi_pin_speed_t; + +typedef enum { + PIN_DRIVE_LV0 = 0U, + PIN_DRIVE_LV1, + PIN_DRIVE_LV2, + PIN_DRIVE_LV3 +} csi_pin_drive_t; + +typedef enum{ + PIN_UART_TX = 0U, + PIN_UART_RX, + PIN_UART_CTS, + PIN_UART_RTS +}csi_pin_uart_t; + +typedef enum{ + PIN_IIC_SCL = 0U, + PIN_IIC_SDA +}csi_pin_iic_t; + +typedef enum{ + PIN_SPI_MISO = 0U, + PIN_SPI_MOSI, + PIN_SPI_SCK, + PIN_SPI_CS +}csi_pin_spi_t; + +typedef enum{ + PIN_I2S_MCLK = 0U, + PIN_I2S_SCLK, + PIN_I2S_WSCLK, + PIN_I2S_SDA, + PIN_I2S_SDI, + PIN_I2S_SDO +}csi_pin_i2s_t; + +typedef struct { + pin_name_t pin_name; + uint8_t idx; ///< ctrl idx. e.g: ADC0 channel 1, idx = 0, channel = 1 + uint8_t channel; ///< channel idx. e.g: same as the previous line + pin_func_t pin_func; +} csi_pinmap_t; + +extern uint32_t target_pin_to_devidx(pin_name_t pin_name, const csi_pinmap_t *pinmap); +extern uint32_t target_pin_to_channel(pin_name_t pin_name,const csi_pinmap_t *pinmap); +extern pin_name_t target_gpio_to_pin(uint8_t gpio_idx, uint8_t channel,const csi_pinmap_t *pinmap); + +/** + \brief Set pin mux function + \param[in] pin_name Pin name, defined in soc.h + \param[in] pin_func Pin function, defined in soc.h + \return \ref csi_error_t +*/ +csi_error_t csi_pin_set_mux(pin_name_t pin_name, pin_func_t pin_func); + +/** + \brief Get pin function + \param[in] pin_name Pin name, defined in soc.h + \return pin function +*/ +pin_func_t csi_pin_get_mux(pin_name_t pin_name); + +/** + \brief Set pin mode + \param[in] pin_name Pin name, defined in soc.h + \param[in] mode Push/pull mode + \return \ref csi_error_t +*/ +csi_error_t csi_pin_mode(pin_name_t pin_name, csi_pin_mode_t mode); + +/** + \brief Set pin speed + \param[in] pin_name Pin name, defined in soc.h + \param[in] speed Io speed + \return \ref csi_error_t +*/ +csi_error_t csi_pin_speed(pin_name_t pin_name, csi_pin_speed_t speed); + +/** + \brief Set pin drive + \param[in] pin_name Pin name, defined in soc.h + \param[in] drive Io drive + \return \ref csi_error_t +*/ +csi_error_t csi_pin_drive(pin_name_t pin_name, csi_pin_drive_t drive); + +/** + \brief Get ctrl idx by pin + \param[in] pin_name Pin name, defined in soc.h + \return idx +*/ +__ALWAYS_STATIC_INLINE uint32_t csi_pin_get_gpio_devidx(pin_name_t pin_name) +{ + extern const csi_pinmap_t gpio_pinmap[]; + return target_pin_to_devidx(pin_name, gpio_pinmap); +} + +__ALWAYS_STATIC_INLINE uint32_t csi_pin_get_uart_devidx(pin_name_t pin_name) +{ + extern const csi_pinmap_t uart_pinmap[]; + return target_pin_to_devidx(pin_name, uart_pinmap); +} + +__ALWAYS_STATIC_INLINE uint32_t csi_pin_get_iic_devidx(pin_name_t pin_name) +{ + extern const csi_pinmap_t iic_pinmap[]; + return target_pin_to_devidx(pin_name, iic_pinmap); +} + +__ALWAYS_STATIC_INLINE uint32_t csi_pin_get_spi_devidx(pin_name_t pin_name) +{ + extern const csi_pinmap_t spi_pinmap[]; + return target_pin_to_devidx(pin_name, spi_pinmap); +} + +__ALWAYS_STATIC_INLINE uint32_t csi_pin_get_i2s_devidx(pin_name_t pin_name) +{ + extern const csi_pinmap_t i2s_pinmap[]; + return target_pin_to_devidx(pin_name, i2s_pinmap); +} + +/** + \brief Get channel by pin + \param[in] pin_name Pin name, defined in soc.h + \return channel +*/ +__ALWAYS_STATIC_INLINE uint32_t csi_pin_get_adc_channel(pin_name_t pin_name) +{ + extern const csi_pinmap_t adc_pinmap[]; + return target_pin_to_channel(pin_name, adc_pinmap); +} + +__ALWAYS_STATIC_INLINE uint32_t csi_pin_get_pwm_channel(pin_name_t pin_name) +{ + extern const csi_pinmap_t pwm_pinmap[]; + return target_pin_to_channel(pin_name, pwm_pinmap); +} + +__ALWAYS_STATIC_INLINE uint32_t csi_pin_get_gpio_channel(pin_name_t pin_name) +{ + extern const csi_pinmap_t gpio_pinmap[]; + return target_pin_to_channel(pin_name, gpio_pinmap); +} + +/** + \brief Get pin name by gpio ctrl idx and channel + \param[in] gpio_idx Idx, defined in soc.h + \param[in] channel Channel, defined in soc.h + \return pin name +*/ +__ALWAYS_STATIC_INLINE pin_name_t csi_pin_get_pinname_by_gpio(uint8_t gpio_idx, uint8_t channel) +{ + extern const csi_pinmap_t gpio_pinmap[]; + return target_gpio_to_pin(gpio_idx,channel,gpio_pinmap); +} + +#endif /* _DRV_PIN_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pm.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pm.h new file mode 100644 index 00000000000..fd5bb4c4e4d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pm.h @@ -0,0 +1,122 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/pm.h + * @brief Header File for PM Driver + * @version V1.0 + * @date 10. Oct 2020 + * @model pm + ******************************************************************************/ + +#ifndef _DRV_PM_H_ +#define _DRV_PM_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + \brief Initialize PM module + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pm_init(void); + +/** + \brief De-initialize PM module + \return None +*/ +void csi_pm_uninit(void); + +/** + \brief Set the retention memory used to save registers + \param[in] mem Retention memory(word align) + \param[in] num Number of memory(1: 1 word) + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pm_set_reten_mem(uint32_t *mem, uint32_t num); + +/** + \brief Config the wakeup source + \param[in] wakeup_num Wakeup source num + \param[in] enable Flag control the wakeup source is enable or not + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pm_config_wakeup_source(uint32_t wakeup_num, bool enable); + +/** + \brief System enter low-power mode + \param[in] mode Low-power mode, \ref csi_pm_mode_t + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pm_enter_sleep(csi_pm_mode_t mode); + +/** + \brief Register device to the PM list + \param[in] dev Csi dev + \param[in] pm_action PM action function + \param[in] mem_size Size of memory for saving registers + \param[in] priority PM dev priority(0-3), The smaller the value, + the last execution before entering low power consumption, + the first execution after exiting low power consumption + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pm_dev_register(csi_dev_t *dev, void *pm_action, uint32_t mem_size, uint8_t priority); + +/** + \brief Deregister device to the PM list + \param[in] dev Csi dev + \return None +*/ +void csi_pm_dev_unregister(csi_dev_t *dev); + +/** + \brief Save registers to memory + \param[in] mem Mem to store registers + \param[in] addr Registers address + \param[in] num Number of memory(1: 1 word) + \return None +*/ +void csi_pm_dev_save_regs(uint32_t *mem, uint32_t *addr, uint32_t num); + +/** + \brief Save registers to memory + \param[in] mem Mem to store registers + \param[in] addr Registers address + \param[in] num Number of memory(1: 1 word) + \return None +*/ +void csi_pm_dev_restore_regs(uint32_t *mem, uint32_t *addr, uint32_t num); + +/** + \brief Notify devices enter low-power states + \param[in] action Device low-power action + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pm_dev_notify(csi_pm_dev_action_t action); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_PM_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pmu.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pmu.h new file mode 100644 index 00000000000..ac5bbadf288 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pmu.h @@ -0,0 +1,118 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv_pmu.h + * @brief header file for pmu driver + * @version V1.0 + * @date 02. June 2017 + * @model pmu + ******************************************************************************/ + +#ifndef _DRV_PMU_H_ +#define _DRV_PMU_H_ + + +#include + +#ifdef __cplusplus +extern "C" { +#endif +/// definition for pmu handle. +typedef void *pmu_handle_t; + +/****** PMU specific error codes *****/ +typedef enum { + EDRV_PMU_MODE = (1), ///< Specified Mode not supported +} pmu_error_e; + +/*----- PMU Control Codes: Mode -----*/ +typedef enum { + PMU_MODE_RUN = 0, ///< Running mode + PMU_MODE_SLEEP, ///< Sleep mode + PMU_MODE_DOZE, ///< Doze mode + PMU_MODE_DORMANT, ///< Dormant mode + PMU_MODE_STANDBY, ///< Standby mode + PMU_MODE_SHUTDOWN ///< Shutdown mode +} pmu_mode_e; + +/*----- PMU Control Codes: Wakeup type -----*/ +typedef enum { + PMU_WAKEUP_TYPE_PULSE = 0, ///< Pulse interrupt + PMU_WAKEUP_TYPE_LEVEL ///< Level interrupt +} pmu_wakeup_type_e; + +/*----- PMU Control Codes: Wakeup polarity -----*/ +typedef enum { + PMU_WAKEUP_POL_LOW = 0, ///< Low or negedge + PMU_WAKEUP_POL_HIGH ///< High or posedge +} pmu_wakeup_pol_e; + +/****** PMU Event *****/ +typedef enum { + PMU_EVENT_SLEEP_DONE = 0, ///< Send completed; however PMU may still transmit data + PMU_EVENT_PREPARE_SLEEP = 1 +} pmu_event_e; + +typedef void (*pmu_event_cb_t)(int32_t idx, pmu_event_e event, pmu_mode_e mode); ///< Pointer to \ref pmu_event_cb_t : PMU Event call back. + +/** + \brief Initialize PMU Interface. 1. Initializes the resources needed for the PMU interface 2.registers event callback function + \param[in] idx the id of the pmu + \param[in] cb_event Pointer to \ref pmu_event_cb_t + \return return pmu handle if success +*/ +pmu_handle_t csi_pmu_initialize(int32_t idx, pmu_event_cb_t cb_event); + +/** + \brief De-initialize PMU Interface. stops operation and releases the software resources used by the interface + \param[in] handle pmu handle to operate. + \return error code +*/ +int32_t csi_pmu_uninitialize(pmu_handle_t handle); + +/** + \brief choose the pmu mode to enter + \param[in] handle pmu handle to operate. + \param[in] mode \ref pmu_mode_e + \return error code +*/ +int32_t csi_pmu_enter_sleep(pmu_handle_t handle, pmu_mode_e mode); + +/** + \brief control pmu power. + \param[in] handle pmu handle to operate. + \param[in] state power state.\ref csi_power_stat_e. + \return error code +*/ +/** + \brief Config the wakeup source. + \param[in] handle pmu handle to operate + \param[in] wakeup_num wakeup source num + \param[in] type \ref pmu_wakeup_type + \param[in] pol \ref pmu_wakeup_pol + \param[in] enable flag control the wakeup source is enable or not + \return error code +*/ +int32_t csi_pmu_config_wakeup_source(pmu_handle_t handle, uint32_t wakeup_num, pmu_wakeup_type_e type, pmu_wakeup_pol_e pol, uint8_t enable); + +#ifdef __cplusplus +} +#endif + +#endif /* _CSI_PMU_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/porting.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/porting.h new file mode 100644 index 00000000000..6ea647a1c42 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/porting.h @@ -0,0 +1,184 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/porting.h + * @brief Header File for SOC Porting + * @version V1.0 + * @date 8. Apr 2020 + * @model porting + ******************************************************************************/ + +#ifndef _DRV_PORTING_H_ +#define _DRV_PORTING_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + BOOTREASON_WDT = 0, // System WDT reset + BOOTREASON_SOFT = 1, // soft reset + BOOTREASON_POWER = 2, // chip power on reset + BOOTREASON_OTHER = 0xFF +} boot_reason_t; + +/* + \brief Soc get boot reason + \return boot reason, \ref boot_reason_t +*/ +boot_reason_t soc_get_boot_reason(void); + +/** + \brief Soc get device frequence. + \param[in] idx Device index + \return frequence +*/ +uint32_t soc_get_apb_freq(uint32_t idx); +uint32_t soc_get_ahb_freq(uint32_t idx); +uint32_t soc_get_cpu_freq(uint32_t idx); + +uint32_t soc_get_uart_freq(uint32_t idx); +uint32_t soc_get_spi_freq(uint32_t idx); +uint32_t soc_get_iic_freq(uint32_t idx); +uint32_t soc_get_i2s_freq(uint32_t idx); +uint32_t soc_get_pwm_freq(uint32_t idx); +uint32_t soc_get_adc_freq(uint32_t idx); +uint32_t soc_get_qspi_freq(uint32_t idx); +uint32_t soc_get_usi_freq(uint32_t idx); +uint32_t soc_get_timer_freq(uint32_t idx); +uint32_t soc_get_rtc_freq(uint32_t idx); +uint32_t soc_get_wdt_freq(uint32_t idx); +uint32_t soc_get_sdio_freq(uint32_t idx); +uint32_t soc_get_emmc_freq(uint32_t idx); +uint32_t soc_get_usb_freq(uint32_t idx); +uint32_t soc_get_ref_clk_freq(uint32_t idx); +uint32_t soc_get_coretim_freq(void); +uint32_t soc_get_cur_cpu_freq(void); +uint32_t soc_get_sys_freq(void); + +/** + \brief Soc get device frequence. + \param[in] freq CPU frequence + \return none +*/ +void soc_set_sys_freq(uint32_t freq); + +/* + \brief Soc init clock unit + \return none +*/ +void soc_clk_init(void); + +/* + \brief Soc enable device clock + \param[in] module Clock module, defined in sys_clk.h, \ref clk_module_t + \return none +*/ +void soc_clk_enable(int32_t module); + +/* + \brief Soc disable device clock + \param[in] module Clock module, defined in sys_clk.h, \ref clk_module_t + \return none +*/ +void soc_clk_disable(int32_t module); + +/* + \brief Get CPU ID + \return CPU ID, the val is 0, 1, 2... +*/ +uint32_t soc_get_cpu_id(void); + +/** + \brief SOC Dcache clean & invalid by range. + \return None +*/ +void soc_dcache_clean_invalid_range(unsigned long addr, uint32_t size); + +/** + \brief SOC Dcache clean & invalid all. + \return None +*/ +void soc_dcache_clean_invalid_all(void); + +/** + \brief SOC Dcache invalid by range. + \return None +*/ +void soc_dcache_invalid_range(unsigned long addr, uint32_t size); + +/** + \brief SOC Dcache invalid all. + \return None +*/ +void soc_dcache_invalid(void); + +/** + \brief SOC Dcache clean all. + \return None +*/ +void soc_dcache_clean(void); + + +/** + \brief SOC Dcache clean by range. + \return None +*/ +void soc_dcache_clean_range(unsigned long addr, uint32_t size); + +/** + \brief SOC Icache invalid all. + \return None +*/ +void soc_icache_invalid(void); + +/** + \brief SOC dma address remap. + \return Remaped address +*/ +extern unsigned long soc_dma_address_remap(unsigned long addr); + + +#ifdef CONFIG_PM +/** + \brief SoC enter low-power mode, each chip's implementation is different + called by csi_pm_enter_sleep + \param[in] mode low-power mode + \return Error code +*/ +csi_error_t soc_pm_enter_sleep(csi_pm_mode_t mode); + +/** + \brief SoC the wakeup source. + \param[in] wakeup_num Wakeup source num + \param[in] enable Flag control the wakeup source is enable or not + \return Error code +*/ +csi_error_t soc_pm_config_wakeup_source(uint32_t wakeup_num, bool enable); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_PORTING_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pwm.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pwm.h new file mode 100644 index 00000000000..0db71e97156 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/pwm.h @@ -0,0 +1,172 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/pwm.h + * @brief Header File for PWM Driver + * @version V1.0 + * @date 9. Oct 2020 + * @model pwm + ******************************************************************************/ + +#ifndef _DRV_PWM_H_ +#define _DRV_PWM_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PWM_POLARITY_HIGH = 0U, ///< High level + PWM_POLARITY_LOW ///< Low level +} csi_pwm_polarity_t; + +typedef enum { + PWM_CAPTURE_POLARITY_POSEDGE = 0U, ///< Posedge Edge + PWM_CAPTURE_POLARITY_NEGEDGE, ///< Negedge Edge + PWM_CAPTURE_POLARITY_BOTHEDGE ///< Both Edge +} csi_pwm_capture_polarity_t; + +typedef enum { + PWM_EVENT_CAPTURE_POSEDGE = 0U, ///< Capture Posedge Event + PWM_EVENT_CAPTURE_NEGEDGE, ///< Capture Negedge Event + PWM_EVENT_CAPTURE_BOTHEDGE, ///< Capture Bothedge Event + PWM_EVENT_ERROR, ///< Error +} csi_pwm_event_t; + +typedef struct csi_pwm csi_pwm_t; + +struct csi_pwm { + csi_dev_t dev; + void (*callback)(csi_pwm_t *pwm, csi_pwm_event_t event, uint32_t ch, uint32_t time_us, void *arg); + void *arg; + void *priv; +}; + +/** + \brief Initialize PWM interface. Initializes the resources needed for the PWM interface + \param[in] pwm Handle to operate + \param[in] idx PWM idx + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pwm_init(csi_pwm_t *pwm, uint32_t idx); + +/** + \brief De-initialize PWM interface. Stops operation and releases the software resources used by the interface + \param[in] pwm Handle to operate + \return None +*/ +void csi_pwm_uninit(csi_pwm_t *pwm); + +/** + \brief Config PWM out mode + \param[in] pwm Handle to operate + \param[in] channel Channel num + \param[in] period_us The PWM period in us + \param[in] pulse_width_us The PMW pulse width in us + \param[in] polarity The PWM polarity \ref csi_pwm_polarity_t + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pwm_out_config(csi_pwm_t *pwm, + uint32_t channel, + uint32_t period_us, + uint32_t pulse_width_us, + csi_pwm_polarity_t polarity); + +/** + \brief Start generate PWM signal + \param[in] pwm Handle to operate + \param[in] channel Channel num + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pwm_out_start(csi_pwm_t *pwm, uint32_t channel); + +/** + \brief Stop generate PWM signal + \param[in] pwm Handle to operate + \param[in] channel Channel num + \return None +*/ +void csi_pwm_out_stop(csi_pwm_t *pwm, uint32_t channel); + +/** + \brief Config PWM capture mode + \param[in] pwm Handle to operate + \param[in] channel Channel num + \param[in] polarity PWM capture polarity \ref csi_pwm_capture_polarity_t + \param[in] count PWM capture polarity count + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pwm_capture_config(csi_pwm_t *pwm, + uint32_t channel, + csi_pwm_capture_polarity_t polarity, + uint32_t count); + +/** + \brief Start PWM capture + \param[in] pwm Handle to operate + \param[in] channel Channel num + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pwm_capture_start(csi_pwm_t *pwm, uint32_t channel); + +/** + \brief Stop PWM capture + \param[in] pwm Handle to operate + \param[in] channel Channel num + \return None +*/ +void csi_pwm_capture_stop(csi_pwm_t *pwm, uint32_t channel); + +/** + \brief Attach PWM callback + \param[in] pwm Handle to operate + \param[in] callback Callback func + \param[in] arg Callback's param + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pwm_attach_callback(csi_pwm_t *pwm, void *callback, void *arg); + +/** + \brief Detach PWM callback + \param[in] pwm Handle to operate + \return None +*/ +void csi_pwm_detach_callback(csi_pwm_t *pwm); + +/** + \brief Enable PWM power manage + \param[in] pwm Handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_pwm_enable_pm(csi_pwm_t *pwm); + +/** + \brief Disable PWM power manage + \param[in] pwm Handle to operate + \return None +*/ +void csi_pwm_disable_pm(csi_pwm_t *pwm); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_PWM_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/qspi.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/qspi.h new file mode 100644 index 00000000000..e8f33312d52 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/qspi.h @@ -0,0 +1,304 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/qspi.h + * @brief Header File for QSPI Driver + * @version V1.0 + * @date 8. Apr 2020 + * @model qspi + ******************************************************************************/ + +#ifndef _DRV_QSPI_H_ +#define _DRV_QSPI_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \enum csi_qspi_clock_mode_t + * \brief QSPI clock mode + */ +typedef enum { + QSPI_CLOCK_MODE_0 = 0, ///< Clock Polarity 0, Clock Phase 0 + QSPI_CLOCK_MODE_1, ///< Clock Polarity 0, Clock Phase 1 + QSPI_CLOCK_MODE_2, ///< Clock Polarity 1, Clock Phase 0 + QSPI_CLOCK_MODE_3, ///< Clock Polarity 1, Clock Phase 1 +} csi_qspi_mode_t; + +/** + * \enum csi_qspi_bus_width_t + * \brief QSPI bus width + */ +typedef enum { + QSPI_CFG_BUS_SINGLE = 0, ///< Single line + QSPI_CFG_BUS_DUAL, ///< Two line + QSPI_CFG_BUS_QUAD, ///< Four line +} csi_qspi_bus_width_t; + +/** + * \enum csi_qspi_address_size_t + * \brief Address size in bits + */ +typedef enum { + QSPI_ADDRESS_8_BITS = 0, + QSPI_ADDRESS_16_BITS, + QSPI_ADDRESS_24_BITS, + QSPI_ADDRESS_32_BITS, +} csi_qspi_address_size_t; + +/** + * \enum csi_qspi_alternate_bytes_size_t + * rief QSPI alternate bytes + */ +typedef enum { + QSPI_ALTERNATE_8_BITS = 0, + QSPI_ALTERNATE_16_BITS, + QSPI_ALTERNATE_24_BITS, + QSPI_ALTERNATE_32_BITS, +} csi_qspi_alt_size_t; + +/** QSPI command + * + * Defines a frame format. It consists of instruction, address, alternative, dummy count and data + */ +typedef struct { + struct { + csi_qspi_bus_width_t bus_width; ///< Bus width for the instruction + uint8_t value; ///< Instruction value + bool disabled; ///< Instruction phase skipped if disabled is set to true + } instruction; + struct { + csi_qspi_bus_width_t bus_width; ///< Bus width for the address + csi_qspi_address_size_t size; ///< Address size + uint32_t value; ///< Address value + bool disabled; ///< Address phase skipped if disabled is set to true + } address; + struct { + csi_qspi_bus_width_t bus_width; ///< Bus width for alternative + csi_qspi_alt_size_t size; ///< Alternative size + uint32_t value; ///< Alternative value + bool disabled; ///< Alternative phase skipped if disabled is set to true + } alt; + uint8_t dummy_count; ///< Dummy cycles count + struct { + csi_qspi_bus_width_t bus_width; ///< Bus width for data + } data; + uint8_t ddr_enable; +} csi_qspi_command_t; + +/** + * \enum csi_qspi_event_t + * \brief QSPI event + */ +typedef enum { + QSPI_EVENT_COMMAND_COMPLETE = 0, ///< Command completed + QSPI_EVENT_ERROR, ///< An error has occurred +} csi_qspi_event_t; + +/** + * \struct csi_qspi_t + * \brief QSPI Handle Structure definition + */ + +typedef struct csi_qspi csi_qspi_t; +struct csi_qspi { + csi_dev_t dev; ///< QSPI hw-device info + void (*callback)(csi_qspi_t *qspi, csi_qspi_event_t event, void *arg); ///< User callback function + void *arg; ///< QSPI custom designed param passed to evt_cb + uint8_t *tx_data; ///< Pointer to QSPI Tx transfer Buffer + uint32_t tx_size; ///< QSPI Tx Transfer size + uint8_t *rx_data; ///< Pointer to QSPI Rx transfer Buffer + uint32_t rx_size; ///< QSPI Rx Transfer size + void *send; ///< The send_async func + void *receive; ///< The receive_async func + void *send_receive; ///< The send_receive_async func + csi_state_t state; ///< Peripheral state + csi_dma_ch_t *tx_dma; + csi_dma_ch_t *rx_dma; + void *priv; +}; + +/** + \brief Init QSPI ctrl block + 1. Initializes the QSPI mode according to the specified parameters in the csi_qspi_init_t + 2. Registers event callback function and user param for the callback + \param[in] qspi Handle of QSPI instance + \param[in] idx Index of instance + \return Error code +*/ +csi_error_t csi_qspi_init(csi_qspi_t *qspi, uint32_t idx); + + +/** + \brief De-initialize QSPI Instance + stops operation and releases the software resources used by the Instance + \param[in] qspi Handle of QSPI instance +*/ +void csi_qspi_uninit(csi_qspi_t *qspi); + +/** + \brief Attach the callback handler to QSPI + \param[in] qspi Operate handle + \param[in] callback Callback function + \param[in] arg User can define it by himself as callback's param + \return Error code +*/ +csi_error_t csi_qspi_attach_callback(csi_qspi_t *qspi, void *callback, void *arg); + +/** + \brief Detach the callback handler + \param[in] qspi Operate handle + \return None +*/ +void csi_qspi_detach_callback(csi_qspi_t *qspi); + +/** + \brief Config qspi frequence + \param[in] qspi Handle of qspi instance + \param[in] hz QSPI frequence + \return The actual config frequency +*/ +uint32_t csi_qspi_frequence(csi_qspi_t *qspi, uint32_t hz); + +/** + \brief Config qspi mode + \param[in] qspi Handle of qspi instance + \param[in] mode QSPI mode + \return Error code +*/ +csi_error_t csi_qspi_mode(csi_qspi_t *qspi, csi_qspi_mode_t mode); + +/** + \brief Send an amount of data in blocking mode + \param[in] qspi QSPI handle + \param[in] cmd Structure that contains the command configuration information + \param[in] data Pointer to data buffer + \param[in] size Size of data to send + \param[in] timeout Time out duration + \return If send successful, this function shall return the num of data witch is sent successful + otherwise, the function shall return error code + */ +int32_t csi_qspi_send(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *data, uint32_t size, uint32_t timeout); + +/** + \brief Receive an amount of data in blocking mode + \param[in] qspi QSPI handle + \param[in] cmd Structure that contains the command configuration information + \param[out] data Pointer to data buffer + \param[in] size Size of data items to receive + \param[in] timeout Time out duration + \return If receive successful, this function shall return the num of data witch is received successfulful + otherwise, the function shall return error code + */ +int32_t csi_qspi_receive(csi_qspi_t *qspi, csi_qspi_command_t *cmd, void *data, uint32_t size, uint32_t timeout); + +/** + \brief Transfer an amount of data in blocking mode + \param[in] qspi QSPI handle + \param[in] cmd Structure that contains the command configuration information + \param[in] tx_data Pointer to send data buffer + \param[out] rx_data Pointer to receive data buffer + \param[in] size Size of data to transfer + \param[in] timeout Time out duration + \return If transfer successful, this function shall return the num of data witch is transfer successfulful + otherwise, the function shall return error code + */ +int32_t csi_qspi_send_receive(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *tx_data, void *rx_data, uint32_t size, uint32_t timeout); + +/** + \brief Send an amount of data in async mode + \param[in] qspi QSPI handle + \param[in] cmd Structure that contains the command configuration information + \param[in] data Pointer to data buffer + \param[in] size Size of data to send + \return Data number send + */ +csi_error_t csi_qspi_send_async(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *data, uint32_t size); + +/** + \brief Receive an amount of data in async mode + \param[in] qspi QSPI handle + \param[in] cmd Structure that contains the command configuration information + \param[out] data Pointer to data buffer + \param[in] size Size of data items to receive + \return Data number received + */ +csi_error_t csi_qspi_receive_async(csi_qspi_t *qspi, csi_qspi_command_t *cmd, void *data, uint32_t size); + +/** + \brief Transfer an amount of data in async mode + \param[in] qspi QSPI handle + \param[in] cmd Structure that contains the command configuration information + \param[in] tx_data Pointer to send data buffer + \param[out] rx_data Pointer to receive data buffer + \param[in] size Size of data to transfer + \return Data number transfered + */ +csi_error_t csi_qspi_send_receive_async(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *tx_data, void *rx_data, uint32_t size); + +/** + \brief Link DMA channel to qspi device + \param[in] qspi QSPI handle to operate + \param[in] tx_dma The DMA channel handle for send, when it is NULL means to unlink the channel + \param[in] rx_dma The DMA channel handle for receive, when it is NULL means to unlink the channel + \return Error code +*/ +csi_error_t csi_qspi_link_dma(csi_qspi_t *qspi, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma); + +/** + \brief Get the state of qspi device + \param[in] qspi QSPI handle + \param[in] state QSPI state \ref csi_state_t + \return Error code + */ +csi_error_t csi_qspi_get_state(csi_qspi_t *qspi, csi_state_t *state); + +/** + \brief Comfigure the memory mapped mode + \param[in] qspi QSPI handle + \param[in] cmd Structure that contains the command configuration information + \return Error code + */ +csi_error_t csi_qspi_memory_mapped(csi_qspi_t *qspi, csi_qspi_command_t *cmd); + +/** + \brief Enable qspi power manage + \param[in] qspi QSPI handle to operate + \return Error code +*/ +csi_error_t csi_qspi_enable_pm(csi_qspi_t *qspi); + +/** + \brief Disable qspi power manage + \param[in] qspi QSPI handle to operate + \return None +*/ +void csi_qspi_disable_pm(csi_qspi_t *qspi); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_QSPI_H_*/ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ringbuf.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ringbuf.h new file mode 100644 index 00000000000..e5006e162c2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/ringbuf.h @@ -0,0 +1,62 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** +* @file ringbuffer.h +* @brief header file for ringbuffer Driver +* @version V1.0 +* @date August 15. 2019 +******************************************************************************/ +#ifndef _RING_BUFFER_H_ +#define _RING_BUFFER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stdint.h" +#include + +typedef struct ringbuffer { + uint8_t *buffer; + uint32_t size; + uint32_t write; + uint32_t read; + uint32_t data_len; +} csi_ringbuf_t; + +void csi_ringbuf_reset(csi_ringbuf_t *fifo); +uint32_t csi_ringbuf_len(csi_ringbuf_t *fifo); +uint32_t csi_ringbuf_avail(csi_ringbuf_t *fifo); +bool csi_ringbuf_is_empty(csi_ringbuf_t *fifo); +bool csi_ringbuf_is_full(csi_ringbuf_t *fifo); + +/*write to ringbuffer*/ +uint32_t csi_ringbuf_in(csi_ringbuf_t *fifo, const void *in, uint32_t len); + +/*read to ringbuffer*/ +uint32_t csi_ringbuf_out(csi_ringbuf_t *fifo, void *out, uint32_t len); + +/*move to another ringbuffer*/ +uint32_t csi_ringbuf_move(csi_ringbuf_t *fifo_in, csi_ringbuf_t *fifo_out); + +#ifdef __cplusplus +} +#endif + +#endif /* _RING_BUFFER_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rng.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rng.h new file mode 100644 index 00000000000..11e03f44d1e --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rng.h @@ -0,0 +1,54 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/tng.h + * @brief Header File for RNG Driver + * @version V1.0 + * @date 22. Apr 2020 + * @model tng + ******************************************************************************/ +#ifndef _DRV_TNG_H_ +#define _DRV_TNG_H_ + +#include "drv/common.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + \brief Get data from the TNG engine + \param[out] Data Pointer to buffer with data get from TNG + \param[in] Num Number of data items,uinit in uint32 + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rng_get_multi_word(uint32_t *data, uint32_t num); + +/** + \brief Get data from the TNG engine + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rng_get_single_word(uint32_t* data); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_TNG_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rsa.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rsa.h new file mode 100644 index 00000000000..0229eb5785a --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rsa.h @@ -0,0 +1,198 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ +/****************************************************************************** + * @file drv/rsa.h + * @brief Header File for RSA Driver + * @version V1.0 + * @date 02. June 2020 + * @model rsa + ******************************************************************************/ +#ifndef _DRV_RSA_H_ +#define _DRV_RSA_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/*----- RSA Control Codes: Mode Parameters: Key Bits -----*/ +/****** RSA Key bits Type *****/ +typedef enum { + RSA_KEY_BITS_192 = 0U, /* 192 Key bits */ + RSA_KEY_BITS_256, /* 256 Key bits */ + RSA_KEY_BITS_512, /* 512 Key bits */ + RSA_KEY_BITS_1024, /* 1024 Key bits */ + RSA_KEY_BITS_2048, /* 2048 Key bits */ + RSA_KEY_BITS_3072, /* 3072 Key bits */ + RSA_KEY_BITS_4096 /* 4096 Key bits */ +} csi_rsa_key_bits_t; + +/****** RSA Padding Type *****/ +typedef enum { + RSA_PADDING_MODE_NO = 0, /* RSA NO Padding Mode */ + RSA_PADDING_MODE_PKCS1, /* RSA PKCS1 Padding Mode */ + RSA_PADDING_MODE_PKCS1_OAEP, /* RSA PKCS1 OAEP Padding Mode */ + RSA_PADDING_MODE_SSLV23, /* RSA SSLV23 Padding Mode */ + RSA_PADDING_MODE_X931, /* RSA X931 Padding Mode */ + RSA_PADDING_MODE_PSS /* RSA PSS Padding Mode */ +} csi_rsa_padding_type_t; + +/****** RSA Hash Type *****/ +typedef enum { + RSA_HASH_TYPE_MD5 = 0, + RSA_HASH_TYPE_SHA1, + RSA_HASH_TYPE_SHA224, + RSA_HASH_TYPE_SHA256, + RSA_HASH_TYPE_SHA384, + RSA_HASH_TYPE_SHA512 +} csi_rsa_hash_type_t; + +/****** RSA Context *****/ +typedef struct { + void *n; /* Pointer to the public modulus */ + void *e; /* Pointer to the public exponent */ + void *d; /* Pointer to the private exponent */ + csi_rsa_key_bits_t key_bits; /* RSA KEY BITS */ + csi_rsa_padding_type_t padding_type; /* RSA PADDING TYPE */ +} csi_rsa_context_t; + +/****** RSA State *****/ +typedef struct { + uint8_t busy : 1; /* Calculate busy flag */ + uint8_t error : 1; /* Calculate error flag */ +} csi_rsa_state_t; + +/****** RSA Ctrl *****/ +typedef struct { + csi_dev_t dev; + void *cb; + void *arg; + csi_rsa_state_t state; + void *prim; +} csi_rsa_t; + +/****** RSA Moddle *****/ +typedef struct { + uint32_t pout[64]; + uint8_t *pouts; + uint32_t *pout_size; + uint32_t u32keywords; + uint8_t *pdst; + uint32_t u32padding; + uint32_t u32dst_words; + uint32_t u32type; + uint32_t rsa_state; +}rsa_middle_t; + +/****** RSA Event *****/ +typedef enum { + RSA_EVENT_COMPLETE = 0, /* rsa event completed */ + RSA_EVENT_VERIFY_SUCCESS, /* rsa event verify success */ + RSA_EVENT_VERIFY_FAILED, /* rsa event verify failed */ + RSA_EVENT_ERROR, /* rsa event error */ +} csi_rsa_event_t; + +typedef void (*csi_rsa_callback_t)(csi_rsa_t *rsa, csi_rsa_event_t event, void *arg); ///< Pointer to \ref csi_rsa_callback_t : RSA Event call back. + +/** + \brief Initialize RSA Interface. 1. Initializes the resources needed for the RSA interface 2.registers event callback function + \param[in] rsa RSA handle to operate. + \param[in] idx Device id + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rsa_init(csi_rsa_t *rsa, uint32_t idx); + +/** + \brief De-initialize RSA Interface. stops operation and releases the software resources used by the interface + \param[in] rsa RSA handle to operate. + \return none +*/ +void csi_rsa_uninit(csi_rsa_t *rsa); + +/** + \brief Generate rsa key pair. + \param[in] rsa RSA handle to operate. + \param[out] context Pointer to the rsa context + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rsa_gen_key(csi_rsa_t *rsa, csi_rsa_context_t *context); + +/** + \brief Encrypt + \param[in] rsa RSA handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size The source data len + \param[out] out Pointer to the result buffer + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rsa_encrypt(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *out); + +/** + \brief decrypt + \param[in] rsa RSA handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size The source data len + \param[out] out Pointer to the result buffer + \param[out] out_size The result size + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rsa_decrypt(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *out, uint32_t *out_size); + +/** + \brief RSA sign + \param[in] rsa RSA handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size The source data len + \param[out] signature Pointer to the signature + \param[in] hash_type The source data hash type + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rsa_sign(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *signature, csi_rsa_hash_type_t hash_type); + +/** + \brief RSA verify + \param[in] rsa RSA handle to operate. + \param[in] context Pointer to the rsa context + \param[in] src Pointer to the source data. + \param[in] src_size The source data len + \param[in] signature Pointer to the signature + \param[in] sig_size The signature size + \param[in] hash_type The source data hash type + \return Verify result +*/ +bool csi_rsa_verify(csi_rsa_t *rsa, csi_rsa_context_t *context, void *src, uint32_t src_size, void *signature, uint32_t sig_size, csi_rsa_hash_type_t hash_type); + +/** + \brief Get big prime data + \param[in] rsa RSA handle to operate. + \param[in] p Pointer to the prime + \param[in] bit_length Pointer to the prime bit length + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rsa_get_prime(csi_rsa_t *rsa, void *p, uint32_t bit_length); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_RSA_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rtc.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rtc.h new file mode 100644 index 00000000000..29742f3cbf7 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/rtc.h @@ -0,0 +1,148 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/rtc.h + * @brief Header File for RTC Driver + * @version V1.0 + * @date 9. Oct 2020 + * @model rtc + ******************************************************************************/ + +#ifndef _DRV_RTC_H_ +#define _DRV_RTC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****** RTC time ******/ +typedef struct { + int tm_sec; ///< Second. [0-59] + int tm_min; ///< Minute. [0-59] + int tm_hour; ///< Hour. [0-23] + int tm_mday; ///< Day. [1-31] + int tm_mon; ///< Month. [0-11] + int tm_year; ///< Year-1900. [70- ] !NOTE:Set 100 mean 2000 + int tm_wday; ///< Day of week. [0-6 ] !NOTE:Set 0 mean Sunday + int tm_yday; ///< Days in year.[0-365] !NOTE:Set 0 mean January 1st +} csi_rtc_time_t; + +/****** definition for RTC ******/ +typedef struct csi_rtc csi_rtc_t; + +struct csi_rtc { + csi_dev_t dev; + void (*callback)(csi_rtc_t *rtc, void *arg); + void *arg; + void *priv; +}; + +/** + \brief Initialize RTC interface. Initializes the resources needed for the RTC interface + \param[in] rtc Handle to operate + \param[in] idx RTC index + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rtc_init(csi_rtc_t *rtc, uint32_t idx); + +/** + \brief De-initialize RTC interface. Stops operation and releases the software resources used by the interface + \param[in] rtc Handle to operate + \return None +*/ +void csi_rtc_uninit(csi_rtc_t *rtc); + +/** + \brief Set system date and wait for synchro + \param[in] rtc Handle to operate + \param[in] rtctime Pointer to RTC time + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rtc_set_time(csi_rtc_t *rtc, const csi_rtc_time_t *rtctime); + +/** + \brief Set system date but no wait + \param[in] rtc Handle to operate + \param[in] rtctime Pointer to RTC time + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rtc_set_time_no_wait(csi_rtc_t *rtc, const csi_rtc_time_t *rtctime); + +/** + \brief Get system date + \param[in] rtc Handle to operate + \param[out] rtctime Pointer to RTC time + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rtc_get_time(csi_rtc_t *rtc, csi_rtc_time_t *rtctime); + +/** + \brief Get alarm remaining time + \param[in] rtc Handle to operate + \return The remaining time(s) +*/ +uint32_t csi_rtc_get_alarm_remaining_time(csi_rtc_t *rtc); + +/** + \brief Config RTC alarm timer + \param[in] rtc Handle to operate + \param[in] rtctime Time to wake up + \param[in] callback Callback function + \param[in] arg Callback's param + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rtc_set_alarm(csi_rtc_t *rtc, const csi_rtc_time_t *rtctime, void *callback, void *arg); + +/** + \brief Cancel the RTC alarm + \param[in] rtc Handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rtc_cancel_alarm(csi_rtc_t *rtc); + +/** + \brief Judge RTC is running + \param[in] rtc Handle to operate + \return + true - RTC is running + false - RTC is not running +*/ +bool csi_rtc_is_running(csi_rtc_t *rtc); + +/** + \brief Enable RTC power manage + \param[in] rtc Handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_rtc_enable_pm(csi_rtc_t *rtc); + +/** + \brief Disable RTC power manage + \param[in] rtc Handle to operate + \return None +*/ +void csi_rtc_disable_pm(csi_rtc_t *rtc); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_RTC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sasc.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sasc.h new file mode 100644 index 00000000000..6a7f6a049ea --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sasc.h @@ -0,0 +1,144 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/sasc.h + * @brief Header File for SASC driver + * @version V1.0 + * @date 02. June 2020 + * @model sasc + ******************************************************************************/ +#ifndef _DRV_SASC_H_ +#define _DRV_SASC_H_ + + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +typedef enum { + SASC_RW = 0, + SASC_RO = 1, + SASC_WO = 2, + SASC_AP_DENY = 3 +} csi_sasc_ap_t; + +typedef enum { + SASC_DI = 0, + SASC_DO = 1, + SASC_IO = 2, + SASC_DI_DENY = 3 +} csi_sasc_di_t; + +typedef enum { + SASC_RAM_4B = 5, + SASC_RAM_8B = 6, + SASC_RAM_16B = 7, + SASC_RAM_32B = 8, + SASC_RAM_64B = 9, + SASC_RAM_128B = 10, + SASC_RAM_256B = 11, + SASC_RAM_512B = 12, + SASC_RAM_1KB = 13, + SASC_RAM_2KB = 14, + SASC_RAM_4KB = 15, + SASC_RAM_8KB = 16, + SASC_RAM_16KB = 17, + SASC_RAM_32KB = 18, + SASC_RAM_64KB = 19, + SASC_RAM_128KB = 20, +} csi_sasc_ram_size_t; + +typedef enum { + SASC_FLASH_1S = 0, + SASC_FLASH_2S, + SASC_FLASH_4S, + SASC_FLASH_8S, + SASC_FLASH_16S, + SASC_FLASH_32S, + SASC_FLASH_64S, + SASC_FLASH_128S, + SASC_FLASH_256S, + SASC_FLASH_512S, + SASC_FLASH_1024S, + SASC_FLASH_2048S +} csi_sasc_flash_size_t; + +typedef struct { + csi_sasc_ap_t super_ap; + csi_sasc_ap_t user_ap; + csi_sasc_di_t super_di; + csi_sasc_di_t user_di; + bool is_secure; +} csi_sasc_attr_t; + +/** + \brief Config the sasc ram region attribute. + \param[in] region_id Config region index + \param[in] base_addr Config region base address. + \param[in] size config region size. + \param[in] attr Region attr. + \return Error code +*/ +csi_error_t csi_sasc_ram_config(uint8_t region_id, uint32_t base_addr, csi_sasc_ram_size_t size, csi_sasc_attr_t attr); + +/** + \brief Config the sasc flash region attribute. + \param[in] region_id Config region index + \param[in] base_addr Config region base address. + \param[in] size Config region size. + \param[in] attr Region attr. + \return Error code +*/ +csi_error_t csi_sasc_flash_config(uint8_t region_id, uint32_t base_addr, csi_sasc_flash_size_t size, csi_sasc_attr_t attr); + +/** + \brief Enable sasc ram config. + \param[in] region_id Region index + \return error code +*/ +csi_error_t csi_sasc_ram_enable(uint8_t region_id); + +/** + \brief Enable sasc flash config + \param[in] region_id Config region index + \return error code +*/ +csi_error_t csi_sasc_flash_enable(uint8_t region_id); + +/** + \brief Disable sasc ram config. + \param[in] region_id Region index + \return error code +*/ +csi_error_t csi_sasc_ram_disable(uint8_t region_id); + +/** + \brief Disable sasc flash config + \param[in] region_id Region index + \return error code +*/ +csi_error_t csi_sasc_flash_disable(uint8_t region_id); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_SASC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sdif.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sdif.h new file mode 100644 index 00000000000..0508912ba50 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sdif.h @@ -0,0 +1,441 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/sdif.h + * @brief Header File for SDIF Driver + * @version V1.0 + * @date 28. June 2020 + * @model sdif + ******************************************************************************/ +#ifndef _DRV_SDIF_H_ +#define _DRV_SDIF_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *sdif_handle_t; + +/*! @brief Construct a status code value from a group and code number. */ +#define MAKE_STATUS(group, code) ((((group)*100) + (code))) + +/*! @brief Status group numbers. */ +enum _status_groups { + kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */ + kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */ + kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/ + kStatusGroup_ApplicationRangeStart = 101, /*!< Starting number for application groups. */ +}; + +/*! @brief Generic status return codes. */ +enum _generic_status { + kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0), + kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1), + kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2), + kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3), + kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4), + kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5), + kStatus_NoTransferInProgress = MAKE_STATUS(kStatusGroup_Generic, 6), +}; + +/*! @brief SDIF status */ +enum _sdif_status { + kStatus_SDIF_DescriptorBufferLenError = MAKE_STATUS(kStatusGroup_SDIF, 0U), /*!< Set DMA descriptor failed */ + kStatus_SDIF_InvalidArgument = MAKE_STATUS(kStatusGroup_SDIF, 1U), /*!< invalid argument status */ + kStatus_SDIF_SyncCmdTimeout = MAKE_STATUS(kStatusGroup_SDIF, 2U), /*!< sync command to CIU timeout status */ + kStatus_SDIF_SendCmdFail = MAKE_STATUS(kStatusGroup_SDIF, 3U), /*!< send command to card fail */ + kStatus_SDIF_SendCmdErrorBufferFull = + MAKE_STATUS(kStatusGroup_SDIF, 4U), /*!< send command to card fail, due to command buffer full + user need to resend this command */ + kStatus_SDIF_DMATransferFailWithFBE = + MAKE_STATUS(kStatusGroup_SDIF, 5U), /*!< DMA transfer data fail with fatal bus error , + to do with this error :issue a hard reset/controller reset*/ + kStatus_SDIF_DMATransferDescriptorUnavailable = + MAKE_STATUS(kStatusGroup_SDIF, 6U), /*!< DMA descriptor unavailable */ + kStatus_SDIF_DataTransferFail = MAKE_STATUS(kStatusGroup_SDIF, 6U), /*!< transfer data fail */ + kStatus_SDIF_ResponseError = MAKE_STATUS(kStatusGroup_SDIF, 7U), /*!< response error */ + kStatus_SDIF_DMAAddrNotAlign = MAKE_STATUS(kStatusGroup_SDIF, 8U), /*!< DMA address not align */ +}; + +/*! @brief Type used for all status and error return values. */ +typedef int32_t status_t; + +/*! @brief Computes the number of elements in an array. */ +#if !defined(ARRAY_SIZE) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +/*! Macro to change a value to a given size aligned value */ +#define SDK_SIZEALIGN(var, alignbytes) \ + ((unsigned int)((var) + ((alignbytes)-1)) & (unsigned int)(~(unsigned int)((alignbytes)-1))) + +///< #define assert(__e) ((void)0) +/*! @name Min/max macros */ +#if !defined(MIN) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#if !defined(MAX) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define SDK_ALIGN(var, alignbytes) var + +static inline unsigned long cpu_to_dma(unsigned long addr) +{ + return addr; +} + +static inline unsigned long *ptr_cpu_to_dma(unsigned long *addr) +{ + return (unsigned long *)cpu_to_dma((unsigned long)addr); +} + +typedef enum { + SDIF_ERROR_CMD_CRC_FAIL = (1), ///< Command response received (but CRC check failed) + SDIF_ERROR_DATA_CRC_FAIL, ///< Data block sent/received (CRC check failed) + SDIF_ERROR_CMD_RSP_TIMEOUT, ///< Command response timeout + SDIF_ERROR_DATA_TIMEOUT, ///< Data timeout + SDIF_ERROR_TX_UNDERRUN, ///< Transmit FIFO underrun + SDIF_ERROR_RX_OVERRUN, ///< Receive FIFO overrun + SDIF_ERROR_ADDR_MISALIGNED, ///< Misaligned address + SDIF_ERROR_BLOCK_LEN_ERR, ///< Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length + SDIF_ERROR_ERASE_SEQ_ERR, ///< An error in the sequence of erase command occurs + SDIF_ERROR_BAD_ERASE_PARAM, ///< An invalid selection for erase groups + SDIF_ERROR_WRITE_PROT_VIOLATION, ///< Attempt to program a write protect block + SDIF_ERROR_LOCK_UNLOCK_FAILED, ///< Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card + SDIF_ERROR_COM_CRC_FAILED, ///< CRC check of the previous command failed + SDIF_ERROR_ILLEGAL_CMD, ///< Command is not legal for the card state + SDIF_ERROR_CARD_ECC_FAILED, ///< Card internal ECC was applied but failed to correct the data + SDIF_ERROR_CC_ERR, ///< Internal card controller error + SDIF_ERROR_GENERAL_UNKNOWN_ERR, ///< General or unknown error + SDIF_ERROR_STREAM_READ_UNDERRUN, ///< The card could not sustain data reading in stream rmode + SDIF_ERROR_STREAM_WRITE_OVERRUN, ///< The card could not sustain data programming in stream mode + SDIF_ERROR_CID_CSD_OVERWRITE, ///< CID/CSD overwrite error + SDIF_ERROR_WP_ERASE_SKIP, ///< Only partial address space was erased + SDIF_ERROR_CARD_ECC_DISABLED, ///< Command has been executed without using internal ECC + SDIF_ERROR_ERASE_RESET, ///< Erase sequence was cleared before executing because an out + SDIF_ERROR_AKE_SEQ_ERR, ///< Error in sequence of authentication + SDIF_ERROR_INVALID_VOLTRANGE, ///< Error in case of invalid voltage range + SDIF_ERROR_ADDR_OUT_OF_RANGE, ///< Error when addressed block is out of range + SDIF_ERROR_REQUEST_NOT_APPLICABLE, ///< Error when command request is not applicable + SDIF_ERROR_UNSUPPORTED_FEATURE, ///< Error when feature is not insupported +} sdif_error_e; + +/* Host controller capabilities flag mask */ +typedef enum { + SDIF_SUPPORT_HIGH_SPEED = 0x1U, ///< Support high-speed + SDIF_SUPPORT_DMA_SPEED = 0x2U, ///< Support DMA + SDIF_SUPPORT_USPEND_RESUME = 0x4U, ///< Support suspend/resume + SDIF_SUPPORT_V330 = 0x8U, ///< Support voltage 3.3V + SDIF_SUPPORT_4BIT = 0x10U, ///< Support 4 bit mode + SDIF_SUPPORT_8BIT = 0x20U, ///< Support 8 bit mode +} sdif_capability_flag_e; + +/* \brief define the internal DMA mode */ +typedef enum { + SDIF_CHAIN_DMA_MODE = 0x01U, ///< one descriptor with one buffer,but one descriptor point to another + SDIF_DUAL_DMA_MODE = 0x02U, ///< dual mode is one descriptor with two buffer +} sdif_dma_mode_e; + +/* The command type */ +typedef enum { + SDIF_CARD_COMMAND_NORMAL = 0U, ///< Normal command + SDIF_CARD_COMMAND_SUSPEND = 1U, ///< Suspend command + SDIF_CARD_COMMAND_RESUME = 2U, ///< Resume command + SDIF_CARD_COMMAND_ABORT = 3U, ///< Abort command +} sdif_card_command_type_e; + +/* The command response type */ +typedef enum { + SDIF_CARD_RESPONSE_NONE = 0U, ///< Response type: none + SDIF_CARD_RESPONSE_R1 = 1U, ///< Response type: R1 + SDIF_CARD_RESPONSE_R1b = 2U, ///< Response type: R1b + SDIF_CARD_RESPONSE_R2 = 3U, ///< Response type: R2 + SDIF_CARD_RESPONSE_R3 = 4U, ///< Response type: R3 + SDIF_CARD_RESPONSE_R4 = 5U, ///< Response type: R4 + SDIF_CARD_RESPONSE_R5 = 6U, ///< Response type: R5 + SDIF_CARD_RESPONSE_R5b = 7U, ///< Response type: R5b + SDIF_CARD_RESPONSE_R6 = 8U, ///< Response type: R6 + SDIF_CARD_RESPONSE_R7 = 9U, ///< Response type: R7 +} sdif_card_response_type_e; + +/* \brief define the card bus width type */ +typedef enum { + SDIF_BUS_1BIT_WIDTH = 0U, ///< 1bit bus width, 1bit mode and 4bit mode share one register bit + SDIF_BUS_4BIT_WIDTH = 1U, ///< 4bit mode mask + SDIF_BUS_8BIT_WIDTH = 2U, ///< support 8 bit mode +} sdif_bus_width_e; + +/* \brief Defines the internal DMA configure structure. */ +typedef struct { + bool enable_fix_burst_len; ///< fix burst len enable/disable flag,When set, the AHB will + ///< use only SINGLE, INCR4, INCR8 or INCR16 during start of + ///< normal burst transfers. When reset, the AHB will use SINGLE + ///< and INCR burst transfer operations + + sdif_dma_mode_e mode; ///< define the DMA mode */ + + + uint32_t *dma_des_buffer_start_addr; ///< internal DMA descriptor start address + uint32_t dma_des_buffer_len; ///< internal DMA buffer descriptor buffer len ,user need to pay attention to the + ///< dma descriptor buffer length if it is bigger enough for your transfer + uint8_t dma_dws_skip_len; ///< define the descriptor skip length ,the length between two descriptor + ///< this field is special for dual DMA mode +} sdif_dma_config_t; + +/* \brief sdif callback functions. */ +typedef struct { + void (*card_inserted)(uint32_t idx, void *user_data); ///< card insert call back + void (*card_removed)(uint32_t idx, void *user_data); ///< card remove call back + void (*sdif_interrupt)(uint32_t idx, void *user_data); ///< SDIF card interrupt occurs + void (*dma_des_unavailable)(uint32_t idx, void *user_data);///< DMA descriptor unavailable + void (*command_reload)(uint32_t idx, void *user_data); ///< command buffer full,need re-load + void (*transfer_complete)(uint32_t idx, + void *state, + int32_t status, + void *user_data); /// +#include + +typedef enum { + SENSOR_VDS_3V3_3V3 = 1, + SENSOR_VDS_2V5_3V3, + SENSOR_VDS_1V8_1V8, + SENSOR_VDS_1V5_1V8, + SENSOR_VDS_1V2_1V2, + SENSOR_VDS_1V1_1V2 +}drv_sensor_vds_t; + +typedef enum { + SENSOR_VHS_RANGE_15 = 0, + SENSOR_VHS_RANGE_12, + SENSOR_VHS_RANGE_9, + SENSOR_VHS_RANGE_6, +}drv_sensor_vhs_t; + +typedef enum { + SENSOR_VLS_RANGE_6 = 0, + SENSOR_VLS_RANGE_9, + SENSOR_VLS_RANGE_12, + SENSOR_VLS_RANGE_15, +}drv_sensor_vls_t; + +typedef enum { + SENSOR_TDHS_NEG_55 = 0, ///< -55 + SENSOR_TDHS_NEG_50, + SENSOR_TDHS_NEG_45, + SENSOR_TDHS_NEG_40, + SENSOR_TDHS_NEG_35, + SENSOR_TDHS_NEG_30, + SENSOR_TDHS_NEG_25, + SENSOR_TDHS_NEG_20, + SENSOR_TDHS_NEG_15, + SENSOR_TDHS_NEG_10, + SENSOR_TDHS_NEG_5, + SENSOR_TDHS_NEG_0, + SENSOR_TDHS_POS_5, ///< +5 + SENSOR_TDHS_POS_10, + SENSOR_TDHS_POS_15, + SENSOR_TDHS_POS_20, + SENSOR_TDHS_POS_25, + SENSOR_TDHS_POS_30, + SENSOR_TDHS_POS_35, + SENSOR_TDHS_POS_40, + SENSOR_TDHS_POS_45, + SENSOR_TDHS_POS_50, + SENSOR_TDHS_POS_55, + SENSOR_TDHS_POS_60, + SENSOR_TDHS_POS_65, + SENSOR_TDHS_POS_70, + SENSOR_TDHS_POS_75, + SENSOR_TDHS_POS_80, + SENSOR_TDHS_POS_85, + SENSOR_TDHS_POS_90, + SENSOR_TDHS_POS_95, + SENSOR_TDHS_POS_100, + SENSOR_TDHS_POS_105, + SENSOR_TDHS_POS_110, + SENSOR_TDHS_POS_115, + SENSOR_TDHS_POS_120, + SENSOR_TDHS_POS_125 +}drv_sensor_tdhs_t; + +typedef enum { + SENSOR_TDLS_NEG_55 = 0, ///< -55 + SENSOR_TDLS_NEG_50, + SENSOR_TDLS_NEG_45, + SENSOR_TDLS_NEG_40, + SENSOR_TDLS_NEG_35, + SENSOR_TDLS_NEG_30, + SENSOR_TDLS_NEG_25, + SENSOR_TDLS_NEG_20, + SENSOR_TDLS_NEG_15, + SENSOR_TDLS_NEG_10, + SENSOR_TDLS_NEG_5, + SENSOR_TDLS_NEG_0, + SENSOR_TDLS_POS_5, ///< +5 + SENSOR_TDLS_POS_10, + SENSOR_TDLS_POS_15, + SENSOR_TDLS_POS_20, +}drv_sensor_tdls_t; + +typedef enum { + SENSOR_FHS_RANGE_50 = 0, + SENSOR_FHS_RANGE_30, + SENSOR_FHS_RANGE_10, + SENSOR_FHS_RANGE_5, +}drv_sensor_fhs_t; + +typedef enum { + SENSOR_FLS_RANGE_50 = 0, + SENSOR_FLS_RANGE_30, + SENSOR_FLS_RANGE_10, + SENSOR_FLS_RANGE_5, +}drv_sensor_fls_t; + +typedef enum { + SENSOR_FHS_FREQ_33M = 0, + SENSOR_FHS_FREQ_66M, + SENSOR_FHS_FREQ_24M, + SENSOR_FHS_FREQ_12M, + SENSOR_FHS_FREQ_99M, + SENSOR_FHS_FREQ_198M, + SENSOR_FHS_FREQ_72M, + SENSOR_FHS_FREQ_36M, +}drv_sensor_freq_t; + +typedef enum { + SENSOR_WARN_H = 0, + SENSOR_WARN_L, + SENSOR_WARN_RST, +}drv_sensor_warn_t; + +/** + \brief Initialize Sensor VD + \param[in] vds Voltage range + \param[in] vhs Voltage high threshold + \param[in] vls Voltage low threshold + \param[in] vtm Used to modify the threshold value of the voltage detection point + \return Error code +*/ +csi_error_t drv_sensor_vd_init(drv_sensor_vds_t vds,drv_sensor_vhs_t vhs,drv_sensor_vls_t vls,uint8_t vtm); + +/** + \brief Get vd warn + \param[in] warn Vd warn select + \return Vd warn code +*/ +uint32_t drv_sensor_vd_get_warn(drv_sensor_warn_t warn); + +/** + \brief Initialize Sensor td + \param[in] hs Temp high threshold + \param[in] ls Temp low threshold + \return Error code +*/ +csi_error_t drv_sensor_td_init(drv_sensor_tdhs_t hs,drv_sensor_tdls_t ls); + +/** + \brief Get td warn + \param[in] warn Td warn select + \return Td warn code +*/ +uint32_t drv_sensor_td_get_warn(drv_sensor_warn_t warn); + +/** + \brief Initialize Sensor FD + \param[in] hs Temp high threshold + \param[in] ls Temp low threshold + \return Error code +*/ +csi_error_t drv_sensor_fd_init(drv_sensor_freq_t freq,drv_sensor_fhs_t fhs,drv_sensor_fls_t fls); + +/** + \brief Get fd warn + \param[in] warn Fd warn select + \return FD warn code +*/ +uint32_t drv_sensor_fd_get_warn(drv_sensor_warn_t warn); + +#endif /* _DRV_SENSOR_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sha.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sha.h new file mode 100644 index 00000000000..bbc23598e60 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/sha.h @@ -0,0 +1,128 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/sha.h + * @brief Header File for SHA Driver + * @version V1.0 + * @date 9. Oct 2020 + * @model sha + ******************************************************************************/ + +#ifndef _DRV_SHA_H_ +#define _DRV_SHA_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****** SHA mode ******/ +typedef enum { + SHA_MODE_1 = 1U, /* SHA_1 mode */ + SHA_MODE_256, /* SHA_256 mode */ + SHA_MODE_224, /* SHA_224 mode */ + SHA_MODE_512, /* SHA_512 mode */ + SHA_MODE_384, /* SHA_384 mode */ + SHA_MODE_512_256, /* SHA_512_256 mode */ + SHA_MODE_512_224, /* SHA_512_224 mode */ + SHA_MODE_MD5 /* MD5 mode */ +} csi_sha_mode_t; + +/****** SHA State ******/ +typedef struct { + uint32_t busy : 1; /* Calculate busy flag */ + uint32_t error : 1; /* Calculate error flag */ +} csi_sha_state_t; + +/****** SHA Context ******/ +typedef struct { + csi_sha_mode_t mode; /* SHA mode */ + uint32_t total[2]; /* Number of bytes processed */ + uint32_t state[16]; /* Intermediate digest state */ + uint8_t buffer[128]; /* Data block being processed */ +} csi_sha_context_t; + +/****** SHA Event ******/ +typedef enum { + SHA_EVENT_COMPLETE = 0U, /*Calculate completed*/ + SHA_EVENT_ERROR /*Calculate error*/ +} csi_sha_event_t; + +/****** SHA Ctrl ******/ +typedef struct csi_sha csi_sha_t; +struct csi_sha{ + csi_dev_t dev; + void (*callback)(csi_sha_t *sha, csi_sha_event_t event, void *arg); /* SHA event callback for user */ + void *arg; /* SHA custom designed param passed to evt_cb */ + csi_dma_ch_t *dma_in; /* SHA in dma handle param */ + csi_sha_state_t state; /* SHA state */ + void *priv; +}; + +/** + \brief Initialize SHA Interface. Initializes the resources needed for the SHA interface + \param[in] sha Operate handle + \param[in] idx Index of SHA + \return Error code \ref csi_error_t +*/ +csi_error_t csi_sha_init(csi_sha_t *sha, uint32_t idx); + +/** + \brief De-initialize SHA Interface. Stops operation and releases the software resources used by the interface + \param[in] sha SHA handle to operate + \return None +*/ +void csi_sha_uninit(csi_sha_t *sha); + +/** + \brief Start the engine + \param[in] sha Handle to operate + \param[in] context Pointer to the SHA context \ref csi_sha_context_t + \param[in] mode SHA mode \ref csi_sha_mode_t + \return Error code \ref csi_error_t +*/ +csi_error_t csi_sha_start(csi_sha_t *sha, csi_sha_context_t *context, csi_sha_mode_t mode); + +/** + \brief Update the engine + \param[in] sha Handle to operate + \param[in] context Pointer to the SHA context \ref csi_sha_context_t + \param[in] input Pointer to the Source data + \param[in] size The data size + \return Error code \ref csi_error_t +*/ +csi_error_t csi_sha_update(csi_sha_t *sha, csi_sha_context_t *context, const void *input, uint32_t size); + +/** + \brief Finish the engine + \param[in] sha Handle to operate + \param[in] context Pointer to the SHA context \ref csi_sha_context_t + \param[out] output Pointer to the result data + \param[out] out_size Pointer to the result data size(bytes) + \return Error code \ref csi_error_t +*/ +csi_error_t csi_sha_finish(csi_sha_t *sha, csi_sha_context_t *context, void *output, uint32_t *out_size); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_SHA_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spi.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spi.h new file mode 100644 index 00000000000..a80bf10543d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spi.h @@ -0,0 +1,293 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/spi.h + * @brief Header File for SPI Driver + * @version V1.0 + * @date 08. Apr 2020 + * @model spi + ******************************************************************************/ + +#ifndef _DRV_SPI_H_ +#define _DRV_SPI_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \enum csi_spi_mode_t + * \brief Function mode of spi + */ +typedef enum { + SPI_MASTER, ///< SPI Master (Output on MOSI, Input on MISO); arg = Bus Speed in bps + SPI_SLAVE, ///< SPI Slave (Output on MISO, Input on MOSI) +} csi_spi_mode_t; + +/** + * \enum csi_spi_frame_len_t + * \brief SPI data width (4bit ~ 16bit) + */ +typedef enum { + SPI_FRAME_LEN_4 = 4, + SPI_FRAME_LEN_5, + SPI_FRAME_LEN_6, + SPI_FRAME_LEN_7, + SPI_FRAME_LEN_8, + SPI_FRAME_LEN_9, + SPI_FRAME_LEN_10, + SPI_FRAME_LEN_11, + SPI_FRAME_LEN_12, + SPI_FRAME_LEN_13, + SPI_FRAME_LEN_14, + SPI_FRAME_LEN_15, + SPI_FRAME_LEN_16 +} csi_spi_frame_len_t; + +/** + * \enum csi_spi_format_t + * \brief Timing format of spi + */ +typedef enum { + SPI_FORMAT_CPOL0_CPHA0 = 0, ///< Clock Polarity 0, Clock Phase 0 + SPI_FORMAT_CPOL0_CPHA1, ///< Clock Polarity 0, Clock Phase 1 + SPI_FORMAT_CPOL1_CPHA0, ///< Clock Polarity 1, Clock Phase 0 + SPI_FORMAT_CPOL1_CPHA1, ///< Clock Polarity 1, Clock Phase 1 +} csi_spi_cp_format_t; + +/** + * \enum csi_spi_event_t + * \brief Signaled event for user by driver + */ +typedef enum { + SPI_EVENT_SEND_COMPLETE, ///< Data Send completed. Occurs after call to csi_spi_send_async to indicate that all the data has been send over + SPI_EVENT_RECEIVE_COMPLETE, ///< Data Receive completed. Occurs after call to csi_spi_receive_async to indicate that all the data has been received + SPI_EVENT_SEND_RECEIVE_COMPLETE, ///< Data Send_receive completed. Occurs after call to csi_spi_send_receive_async to indicate that all the data has been send_received + SPI_EVENT_ERROR_OVERFLOW, ///< Data overflow: Receive overflow + SPI_EVENT_ERROR_UNDERFLOW, ///< Data underflow: Transmit underflow + SPI_EVENT_ERROR ///< Master Mode Fault (SS deactivated when Master).Occurs in master mode when Slave Select is deactivated and indicates Master Mode Fault +} csi_spi_event_t; + +/** + * \struct csi_spi_t + * \brief Ctrl block of spi instance + */ +typedef struct csi_spi csi_spi_t; +struct csi_spi { + csi_dev_t dev; ///< Hw-device info + void (*callback)(csi_spi_t *spi, csi_spi_event_t event, void *arg); ///< User callback ,signaled by driver event + void *arg; ///< User private param ,passed to user callback + uint8_t *tx_data; ///< Output data buf + uint32_t tx_size; ///< Output data size specified by user + uint8_t *rx_data; ///< Input data buf + uint32_t rx_size; ///< Input data size specified by user + csi_error_t (*send)(csi_spi_t *spi, const void *data, uint32_t size); ///< The send_async func + csi_error_t (*receive)(csi_spi_t *spi, void *data, uint32_t size); ///< The receive_async func + csi_error_t (*send_receive)(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size); ///< The send_receive_async func + csi_state_t state; ///< Peripheral state + csi_dma_ch_t *tx_dma; + csi_dma_ch_t *rx_dma; + void *priv; +}; + +/** + \brief Initialize SPI Interface + Initialize the resources needed for the SPI instance + \param[in] spi SPI handle + \param[in] idx SPI instance index + \return Error code +*/ +csi_error_t csi_spi_init(csi_spi_t *spi, uint32_t idx); + +/** + \brief De-initialize SPI Interface + stops Operation and releases the software resources used by the spi instance + \param[in] spi Handle + \return None +*/ +void csi_spi_uninit(csi_spi_t *spi); + +/** + \brief Attach the callback handler to SPI + \param[in] spi Operate handle + \param[in] callback Callback function + \param[in] arg User can define it by himself as callback's param + \return Error code +*/ +csi_error_t csi_spi_attach_callback(csi_spi_t *spi, void *callback, void *arg); + +/** + \brief Detach the callback handler + \param[in] spi Operate handle + \return None +*/ +void csi_spi_detach_callback(csi_spi_t *spi); + +/** + \brief Config spi mode (master or slave) + \param[in] spi SPI handle + \param[in] mode The mode of spi (master or slave) + \return Error code +*/ +csi_error_t csi_spi_mode(csi_spi_t *spi, csi_spi_mode_t mode); + +/** + \brief Config spi cp format + \param[in] spi SPI handle + \param[in] format SPI cp format + \return Error code +*/ +csi_error_t csi_spi_cp_format(csi_spi_t *spi, csi_spi_cp_format_t format); + +/** + \brief Config spi frame len + \param[in] spi SPI handle + \param[in] length SPI frame len + \return Error code +*/ +csi_error_t csi_spi_frame_len(csi_spi_t *spi, csi_spi_frame_len_t length); + +/** + \brief Config spi work frequence + \param[in] spi SPI handle + \param[in] baud SPI work baud + \return the actual config frequency +*/ +uint32_t csi_spi_baud(csi_spi_t *spi, uint32_t baud); + +/** + \brief Sending data to SPI transmitter,(received data is ignored) + blocking mode ,return unti all data has been sent or err happened + \param[in] spi Handle to operate + \param[in] data Pointer to buffer with data to send to SPI transmitter + \param[in] size Number of data to send(byte) + \param[in] timeout Unit in mini-second + \return If send successful, this function shall return the num of data witch is sent successful + otherwise, the function shall return Error code +*/ +int32_t csi_spi_send(csi_spi_t *spi, const void *data, uint32_t size, uint32_t timeout); + +/** + \brief Sending data to SPI transmitter,(received data is ignored) + non-blocking mode,transfer done event will be signaled by driver + \param[in] spi Handle to operate + \param[in] data Pointer to buffer with data to send to SPI transmitter + \param[in] size Number of data items to send(byte) + \return Error code +*/ +csi_error_t csi_spi_send_async(csi_spi_t *spi, const void *data, uint32_t size); + +/** + \brief Receiving data from SPI receiver + blocking mode, return untill curtain data items are readed + \param[in] spi Handle to operate + \param[out] data Pointer to buffer for data to receive from SPI receiver + \param[in] size Number of data items to receive(byte) + \param[in] timeout Unit in mini-second + \return If receive successful, this function shall return the num of data witch is received successful + otherwise, the function shall return Error code +*/ +int32_t csi_spi_receive(csi_spi_t *spi, void *data, uint32_t size, uint32_t timeout); + +/** + \brief Receiving data from SPI receiver + not-blocking mode, event will be signaled when receive done or err happend + \param[in] spi Handle to operate + \param[out] data Pointer to buffer for data to receive from SPI receiver + \param[in] size Number of data items to receive(byte) + \return Error code +*/ +csi_error_t csi_spi_receive_async(csi_spi_t *spi, void *data, uint32_t size); + +/** + \brief Dulplex,sending and receiving data at the same time + \ref csi_spi_event_t is signaled when operation completes or error happens + \ref csi_spi_get_state can get operation status + blocking mode, this function returns after operation completes or error happens + \param[in] spi SPI handle to operate + \param[in] data_out Pointer to buffer with data to send to SPI transmitter + \param[out] data_in Pointer to buffer for data to receive from SPI receiver + \param[in] size Data size(byte) + \return If transfer successful, this function shall return the num of data witch is transfer successful, + otherwise, the function shall return Error code +*/ +int32_t csi_spi_send_receive(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size, uint32_t timeout); + +/** + \brief Transmit first then receive ,receive will begin after transmit is done + if non-blocking mode, this function only starts the transfer, + \ref csi_spi_event_t is signaled when operation completes or error happens + \ref csi_spi_get_state can get operation status + \param[in] spi SPI handle to operate + \param[in] data_out Pointer to buffer with data to send to SPI transmitter + \param[out] data_in Pointer to buffer for data to receive from SPI receiver + \param[in] size Data size(byte) + \return Error code +*/ +csi_error_t csi_spi_send_receive_async(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size); + +/* + \brief Set slave select num. Only valid for master + \param[in] handle SPI handle to operate + \param[in] slave_num SPI slave num + \return None + */ +void csi_spi_select_slave(csi_spi_t *spi, uint32_t slave_num); + +/** + \brief Link DMA channel to spi device + \param[in] spi SPI handle to operate + \param[in] tx_dma The DMA channel handle for send, when it is NULL means to unlink the channel + \param[in] rx_dma The DMA channel handle for receive, when it is NULL means to unlink the channel + \return Error code +*/ +csi_error_t csi_spi_link_dma(csi_spi_t *spi, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma); + +/** + \brief Get the state of spi device + \param[in] spi SPI handle to operate + \param[out] state The state of spi device + \return Error code +*/ +csi_error_t csi_spi_get_state(csi_spi_t *spi, csi_state_t *state); + +/** + \brief Enable spi power manage + \param[in] spi SPI handle to operate + \return Error code +*/ +csi_error_t csi_spi_enable_pm(csi_spi_t *spi); + +/** + \brief Disable spi power manage + \param[in] spi SPI handle to operate + \return Error code +*/ +void csi_spi_disable_pm(csi_spi_t *spi); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_SPI_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spiflash.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spiflash.h new file mode 100644 index 00000000000..64a24ca95fb --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spiflash.h @@ -0,0 +1,303 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/spiflash.h + * @brief Header File for SPIFLASH Driver + * @version V1.0 + * @date 02. June 2020 + * @model spiflash + ******************************************************************************/ +#ifndef _DRV_SPIFLASH_H_ +#define _DRV_SPIFLASH_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* \brief Build a flash ID +* \param [in] vendor_id Vendor id(8bit) +* \param [in] device_id Flash device id (ID15~ID0) 16bit +* \return 24bit flash id +*/ +#define FLASH_ID_BUILD(VENDOR_ID,DEVICE_ID) + +/** +* \struct csi_spiflash_lock_info_t +* \ flash use status register 1 to protect data in memory array +* \ different flash vendor support different protect region (top/bottom/none) +* also support different protect number +* status1 register bif field show as follow +* 7 |6 |5 |4 |3 |2 |1 |0 +* --------------------------------------------------------------------- +* vensor def | vendor def | vendor def | BP2 | BP1 | BP0 | WEL | BUSY +* \ Protect type +* \ Protect block size : Vendor define ,user should check flash datasheet of vendor +* : Use w25q64fw as example , min protect block size is 128 KB +* \ TOP : Protect address from flash top address +* \ BOTTOM : Protect address from flash bottom address +* \ SEC : Protect addres base on sector unit and protect region only must not exceed one block +* \ BPx : Protect start addres base on TOP/BOTTOM feature,and BPx value denote protect number +* \ BP[x..0]'s value : 2^(n-1) protect block unit, ex, BP[x..0] = 5, protect block number = 2^(5-1) = 16 +* \ If BP[x..0] = 0 denote protect none +* \ If BP[x..0]'s all bis is 1 ,denote protect all flash +* \ +* \ NOTE: +* \ only support SEC = 0 +* \ only support CMP = 0 +* \ +* +* Sample table portion for 8MB flash (Winbond w25q64fw): +* +* SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion +* -------------------------------------------------------------------------- +* X | X | 0 | 0 | 0 | NONE | NONE +* 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 +* 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 +* 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 +* 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 +* 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 +* 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 +* X | X | 1 | 1 | 1 | 8 MB | ALL +* ------|-------|-------|-------|-------|---------------|------------------- +* 0 | 1 | 0 | 0 | 1 | 128 KB | Lower 1/64 +* 0 | 1 | 0 | 1 | 0 | 256 KB | Lower 1/32 +* 0 | 1 | 0 | 1 | 1 | 512 KB | Lower 1/16 +* 0 | 1 | 1 | 0 | 0 | 1 MB | Lower 1/8 +* 0 | 1 | 1 | 0 | 1 | 2 MB | Lower 1/4 +* 0 | 1 | 1 | 1 | 0 | 4 MB | Lower 1/2 +* +*/ +typedef enum { + LOCK_TP_NONE, + LOCK_TP_TOP, + LOCK_TP_BOTTOM, + LOCK_TP_DUAL +} csi_spiflash_lock_region_t; +typedef enum { + SPIFLASH_DATA_1_LINE = 1, + SPIFLASH_DATA_2_LINES = 2, + SPIFLASH_DATA_4_LINES = 4 +} csi_spiflash_data_line_t; +typedef union { + csi_spi_t spi; + csi_qspi_t qspi; +} csi_spi_qspi_t; + +/** +\brief Flash information +*/ +typedef struct { + char *flash_name; ///< Name string of spiflash + uint32_t flash_id; ///< JEDEC ID = manufature ID <<16 | device ID (ID15~ID0) + uint32_t flash_size; ///< Flash chip size + uint32_t xip_addr; ///< If use qspi controler to access flash ,code can be ececuted on flash ,the addr is xip addr + uint32_t sector_size; ///< Sector size + uint32_t page_size; ///< Page size for read or program +} csi_spiflash_info_t; + +typedef struct{ + struct{ + uint8_t buswidth; ///< cmd buswidth + }cmd; + struct { + uint8_t buswidth; ///< addr buswidth + }addr; + struct { + uint8_t nbytes; ///< dummy bytes + }dummy; + struct { + uint8_t buswidth; ///< data buswidth + }data; +} csi_spiflash_cmd_t; + +/** +\brief Flash control block +*/ +typedef struct { + csi_spi_qspi_t spi_qspi; ///< Spi/qspi handle + void (*spi_cs_callback)(csi_gpio_pin_state_t value); + void *flash_prv_info; ///< Point to vendor private feature struct + int32_t (*spi_send)(void *spi, uint8_t cmd, uint32_t addr, uint32_t addr_size, const void *data, uint32_t size); + int32_t (*spi_receive)(void *spi, uint8_t cmd, uint32_t addr, uint32_t addr_size, void *data, uint32_t size); + csi_error_t (*set_cmd)(void *spi, csi_spiflash_cmd_t *cmd); + void *priv; ///< User private param +} csi_spiflash_t; + +/** + \brief Initialize SPIFLASH with spi controler and probe flash device + \param[in] spiflash SPIFLASH handle + \param[in] spi_idx SPI controler index + \param[in] spi_cs GPIO info for chip select,if NULL, not use gpio cs + \return Error code +*/ +csi_error_t csi_spiflash_spi_init(csi_spiflash_t *spiflash, uint32_t spi_idx, void *spi_cs_callback); + +/** + \brief Initialize SPIFLASH with qspi controler and probe flash device + \param[in] spiflash SPIFLASH handle + \param[in] qspi_idx QSPI controler index + \return Error code +*/ +csi_error_t csi_spiflash_qspi_init(csi_spiflash_t *spiflash, uint32_t qspi_idx, void *qspi_cs_callback); + +/** + \brief De-initialize SPIFLASH Interface based on spi controler. stops operation and releases the software resources used by the interface + \param[in] spiflash SPIFLASH handle to operate + \return Error code +*/ +void csi_spiflash_spi_uninit(csi_spiflash_t *spiflash); + +/** + \brief De-initialize SPIFLASH Interface based on qspi controler. stops operation and releases the software resources used by the interface + \param[in] spiflash SPIFLASH handle to operate + \return Error code +*/ +void csi_spiflash_qspi_uninit(csi_spiflash_t *spiflash); + + +/** + \brief Get flash device infomation + \param[in] spiflash SPIFLASH handle to operate + \param[in] flash_info User storage to get flash vendor info after flash init + \return spiflash_info_t +*/ +csi_error_t csi_spiflash_get_flash_info(csi_spiflash_t *spiflash, csi_spiflash_info_t *flash_info); + + +/** + \brief Read data from Flash + \param[in] spiflash SPIFLASH handle to operate + \param[in] offset Data address, offset address relative to zero + \param[out] data Pointer to a buffer storing the data read from Flash + \param[in] size Number of data items to read + \return If receive successful, this function shall return the num of data witch is received successful + otherwise, the function shall return Error code +*/ +int32_t csi_spiflash_read(csi_spiflash_t *spiflash, uint32_t offset, void *data, uint32_t size); + +/** + \brief Program data to Flash + \param[in] spiflash SPIFLASH handle to operate + \param[in] offset Data address, offset address relative to zero + \param[in] data Pointer to a buffer containing the data to be programmed to Flash. + \param[in] size Number of data items to program + \return If program successful, this function shall return the num of data witch is program successful, + otherwise, the function shall return Error code +*/ +int32_t csi_spiflash_program(csi_spiflash_t *spiflash, uint32_t offset, const void *data, uint32_t size); + +/** + \brief Erase Flash Sector + \param[in] spiflash SPIFLASH handle to operate + \param[in] offset Data address, offset address relative to zero + \param[in] size Length to be erased + \return Error code +*/ +csi_error_t csi_spiflash_erase(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size); + +/** + \brief Read flash status register + \param[in] spiflash SPIFLASH handle to operate + \param[in] cmd_code Cmd code + \param[out] data Data buf to save flash status register + \param[in] size Register length in byte + \return Error code +*/ +csi_error_t csi_spiflash_read_reg(csi_spiflash_t *spiflash, uint8_t cmd_code, uint8_t *data, uint32_t size); + +/** + \brief Write status register + \param[in] spiflash SPIFLASH handle to operate + \param[in] cmd Cmd code + \param[out] data Data buf to save flash status register + \param[in] size Register length in byte + \return Error code +*/ +csi_error_t csi_spiflash_write_reg(csi_spiflash_t *spiflash, uint8_t cmd_code, uint8_t *data, uint32_t size); + + +/** + \brief Enable spiflash write protection + \param[in] spiflash SPIFLASH handle to operate + \param[in] offset Protect flash offset,offset need protect block size aligned + \param[in] size Lock size(byte) + \return Error code +*/ +csi_error_t csi_spiflash_lock(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size); + +/** + \brief Enable spiflash write protection + \param[in] spiflash SPIFLASH handle to operate + \param[in] offset Protect flash offset,offset need protect block size aligned + \param[in] size Unlock size(byte) + \return Error code +*/ +csi_error_t csi_spiflash_unlock(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size); + +/** + \brief check flash is locked(write protect) + \param[in] spiflash SPIFLASH handle to operate + \param[in] offset Protect flash offset,offset need protect block size aligned + \param[in] size Locked size(byte) + \return 0:unlocked if query region overlay with locked region 1: locked if query reigon is fully in locked region +*/ +int csi_spiflash_is_locked(csi_spiflash_t *spiflash, uint32_t offset, uint32_t size); + +/** + \brief Set QSPI data line + \param[in] spiflash SPIFLASH handle to operate + \param[in] line SPIFLASH data line mode + \return Error code +*/ +csi_error_t csi_spiflash_config_data_line(csi_spiflash_t *spiflash, csi_spiflash_data_line_t line); + +/** + \brief Set QSPI frequence + \param[in] spiflash SPIFLASH handle to operate + \param[in] hz SPIFLASH frequence + \return The actual config frequency +*/ +uint32_t csi_spiflash_frequence(csi_spiflash_t *spiflash, uint32_t hz); + +/** + \brief Flash power down. + \param[in] spiflash SPIFLASH handle to operate. + \return error code +*/ +csi_error_t csi_spiflash_release_power_down(csi_spiflash_t *spiflash); + +/** + \brief Flash power release. + \param[in] spiflash SPIFLASH handle to operate. + \return none +*/ +void csi_spiflash_power_down(csi_spiflash_t *spiflash); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_SPIFLASH_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spinand.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spinand.h new file mode 100644 index 00000000000..17f6c6fb2eb --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/spinand.h @@ -0,0 +1,321 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file spinand.h + * @brief header file for spinand driver + * @version V1.0 + * @date 17. Aug 2017 + * @model spinand + ******************************************************************************/ +#ifndef _DRV_NANDFLASH_H_ +#define _DRV_NANDFLASH_H_ + + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPINAND_DEF_SPEED (1000000) +#define SPIANND_DEF_MAX_WAIT_TIME (1000) ///< max wait time in ms + +typedef union { + csi_qspi_t qspi; ///< hold qspi object +} csi_nand_spi_qspi_t; + + +typedef struct { +uint32_t target; ///< target in chip +uint32_t lun; ///< lun in target +uint32_t plane; ///< plane number in lun +uint32_t block; ///< block index in lun +uint32_t page; ///< page index in lun +uint32_t offset; ///< column offset within page +}csi_nand_pos_t; + +typedef enum{ + SPI_MEM_NODATA, ///< no data portion + SPI_MEM_DATA_IN, ///< read data + SPI_MEM_DATA_OUT ///< write data +}csi_spi_mem_dir_t; + +typedef struct{ + + struct{ + uint8_t buswidth; ///< cmd buswidth + uint8_t opcode; ///< cmd code + }cmd; + + struct { + uint8_t buswidth; ///< addr buswidth + uint8_t nbytes; ///< bytes of addr + uint64_t val; ///< addr value + }addr; + + struct { + uint8_t nbytes; ///< dummy bytes + uint8_t buswidth; ///< bus width + }dummy; + + + struct { + uint8_t buswidth; ///< data buswidth + uint32_t nbytes; ///< data len + csi_spi_mem_dir_t dir; ///< data xfer dir + union{ + void* in; ///< read data buf ptr + void* out; ///< write datat buf ptr + }buf; + }data; + +}spi_mem_op_t; + +typedef struct { + const uint8_t *id; ///< point to chip id array + const uint8_t len; ///< id length +}csi_spinand_id_t; + +typedef struct { + uint8_t id[4]; ///< id data + uint8_t len; ///< id length +}csi_nand_id_t; + + +typedef struct{ + uint16_t strength; ///< number of hw-ecc engine bits + uint16_t step_size; ///< corect size by ecc per-step +}csi_nand_ecc_req_t; + +typedef struct { + uint32_t bits_per_cell; ///< bit per-cell + uint32_t pagesize; ///< page size + uint32_t oobsize; ///< spare area size + uint32_t pages_per_eraseblock; ///< pages per block + uint32_t eraseblocks_per_lun; ///< blocks per lun(logic unit number== max block index ) + uint32_t max_bad_eraseblocks_per_lun; ///< max bad blocks per lun + uint32_t planes_per_lun; ///< planes per-lun + uint32_t luns_per_target; ///< luns per die + uint32_t ntargets; ///< target index +}csi_nand_mem_layout_t; + + + +typedef struct { + char *model; ///< chip name of vendor + uint32_t flags; ///< chip-specific feature bits group + csi_spinand_id_t devid; ///< devid of chip + csi_nand_mem_layout_t memorg; ///< mem layout of chip + csi_nand_ecc_req_t eccreq; ///< ecc capabilty of chip + csi_error_t (*select_target)(void *spinand, uint32_t target); ///< select target + csi_error_t (*check_ecc_status)(void *spinand,uint8_t status); ///< check vendor specific ecc status +}csi_spinand_info_t; + + +typedef struct { + csi_error_t (*init) (void *spinand); ///< vendor chip inition + void (*uninit) (void *spinand); ///< vendor chip uninition +}csi_spinand_manufacturer_ops_t; + +typedef struct { + uint8_t id; ///< vendor id + char *name; ///< vendor name + const csi_spinand_info_t *chips; ///< vendor chip param + uint32_t nchips; ///< chips number supported + const csi_spinand_manufacturer_ops_t *ops; ///< vendor specific operations +}csi_spinand_manufacturer_t; + + +typedef struct { + char *model_name; ///< name of nand-device module + uint16_t page_size; ///< page-size of nand-device + uint16_t oob_size; ///< oob-size(spare size) of nand-device + uint16_t pages_per_block; ///< pages-per-block + uint16_t max_bad_blocks; ///< max possible bad blocks of nand-device + uint32_t total_blocks; ///< total blocks of nand-device +}csi_spinand_dev_params_t; + +typedef struct +{ + void *xfer_buf; ///< point to xfer data buf + uint32_t xfer_buf_len; ///< length of xfer buf ,count in byte + uint16_t rxfer_copy_offset; ///< copy offset from word-aligned buf + uint16_t rxfer_origin_len; ///< copy length from word-aligned buf +}csi_xfer_data_buf_t; + + +/** +\brief Flash control block +*/ +typedef struct { + #define SPINAND_SCRAT_BUF_LEN 4 ///< scratch buf len + csi_nand_spi_qspi_t spi_qspi; ///< Spi/qspi handle + uint8_t scractbuf[SPINAND_SCRAT_BUF_LEN]; ///< scracthbuf for read/write id or reg + uint8_t cur_target; ///< current target + uint16_t max_tx_size; ///< max tx op size + uint16_t max_rx_size; ///< max rx op size + csi_xfer_data_buf_t xfer; ///< xfer buf + csi_spinand_info_t *chip_info; ///< Point to vendor private feature struct + csi_spinand_manufacturer_t *maf; ///< point to manufacture + void (*spi_cs_callback)(csi_gpio_pin_state_t value); ///< gpio chip select for spi or qspi + csi_error_t (*spi_mem)(void *spinand,spi_mem_op_t *op); ///< spi-mem op function + void *priv; ///< User private param +} csi_spinand_t; + +typedef enum { + XFER_CPU_POLLING, ///< transfer by qspi with cpu polling mode + XFER_DMA, ///< transfer by qspi with external dma engine + XFER_INTR, ///< transfer by qspi with cpu-interrut +}csi_spinand_xfer_t; + +/** + \brief Initialize NANDFLASH with qspi controler and probe flash device + \param[in] spinand NANDFLASH handle + \param[in] qspi_idx QSPI controler index + \param[in] spi_cs_callback GPIO info for chip select,if NULL, not use gpio cs + \return Error code +*/ +csi_error_t csi_spinand_qspi_init(csi_spinand_t *spinand, uint32_t qspi_idx,void *gpio_cs_callback); + +/** + \brief De-initialize NANDFLASH Interface based on spi controler. stops operation and releases the software resources used by the interface + \param[in] spinand NANDFLASH handle to operate + \return Error code +*/ +void csi_spinand_qspi_uninit(csi_spinand_t *spinand); + +/** + \brief set xfer mode + \param[in] spinand NANDFLASH handle to operate + \param[in] xfer_mode please ref csi_spinand_xfer_t + \return Error code +*/ +csi_error_t csi_spinand_set_xfer_mode(csi_spinand_t *spinand,csi_spinand_xfer_t xfer_mode); + + +/** + \brief get flash device infomation + \param[in] spinand NANDFLASH handle to operate + \param[in] flash_info User storage to get flash vendor info after flash init + \return spinand_info_t +*/ + +csi_error_t csi_spinand_get_flash_info(csi_spinand_t *spinand, csi_spinand_dev_params_t *flash_info); + +/** + \brief Read data from Flash + \param[in] spinand NANDFLASH handle to operate + \param[in] offset Data address, offset address relative to zero + \param[out] data Pointer to a buffer storing the data read from Flash + \param[in] cnt Number of data items to read + \return If receive successful, this function shall return the num of data witch is received successfulful + otherwise, the function shall return Error code +*/ +int32_t csi_spinand_read(csi_spinand_t *spinand, uint64_t offset, void *data, uint32_t size); + + +/** + \brief Read spare data from specific page + \param[in] spinand NANDFLASH handle to operate + \param[in] page_addr page addr, address relative to zero, addr need page size aligned + \param[in] spare_offset offset address within the spare area of the page + \param[out] data Pointer to a buffer storing the data read from Flash + \param[in] size Number of data items to read + \return If receive successful, this function shall return the num of data witch is received successfully + otherwise, the function shall return Error code +*/ +int32_t csi_spinand_read_spare_data(csi_spinand_t *spinand,uint64_t page_addr,uint32_t spare_offset,void *data, uint32_t size); + +/** + \brief write data to Flash + \param[in] spinand NANDFLASH handle to operate + \param[in] offset Data address, offset address relative to zero + \param[in] data Pointer to a buffer containing the data to be programmed to Flash. + \param[in] size Number of data items to program + \return If program successful, this function shall return the num of data witch is programed successfully + otherwise, the function shall return Error code +*/ +int32_t csi_spinand_write(csi_spinand_t *spinand, uint64_t offset, const void *data, uint64_t size); + +/** + \brief write spare data to specific page + \param[in] spinand NANDFLASH handle to operate + \param[in] page_addr page addr, address relative to zero, addr need page size aligned + \param[in] spare_offset offset address within the spare area of the page + \param[out] data Pointer to a buffer storing the data write to Flash + \param[in] size Number of data items to write + \return If program successful, this function shall return the num of data witch is programed successfully + otherwise, the function shall return Error code +*/ +int32_t csi_spinand_write_spare_data(csi_spinand_t *spinand,uint64_t page_addr,uint32_t spare_offset,void *data, uint32_t size); + + +/** + \brief Erase Flash Sector + \param[in] spinand NANDFLASH handle to operate + \param[in] offset Data address, offset address relative to zero + \param[in] size Length to be erased + \param[out] last erased block addr + \return Error code +*/ +csi_error_t csi_spinand_erase(csi_spinand_t *spinand, uint64_t offset, uint64_t size, uint64_t *last_fail_addr); + +/** + \brief check whether the block is bad + \param[in] spinand NANDFLASH handle to operate + \param[in] block_addr block addr (count in bytes) + \return 1: bad 0: not bad <0 err code +*/ + + +int32_t csi_spinand_block_is_bad(csi_spinand_t *spinand,uint64_t block_addr); + +/** + \brief mark block as a bad block + \param[in] spinand NANDFLASH handle to operate + \param[in] block_addr block addr (count in bytes) + \return Error code +*/ +csi_error_t csi_spinand_block_mark_bad(csi_spinand_t *spinand, uint64_t block_addr); + +/** + \brief reset spinand device + \param[in] spinand NANDFLASH handle to operate + \return Error code +*/ +int32_t csi_spinand_reset(csi_spinand_t *spinand); + +/** + \brief Set QSPI frequence + \param[in] spinand NANDFLASH handle to operate + \param[in] hz NANDFLASH frequence + \return The actual config frequency +*/ +uint32_t csi_spinand_frequence(csi_spinand_t *spinand, uint32_t hz); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_NANDFLASH_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tee.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tee.h new file mode 100644 index 00000000000..dc85c7b9fe0 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tee.h @@ -0,0 +1,643 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + + +/****************************************************************************** + * @file drv/tee.h + * @brief Header File for TEE Driver + * @version V1.0 + * @date 12 Sep 2020 + * @model tee + ******************************************************************************/ +#ifndef _DRV_TEE_H_ +#define _DRV_TEE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif +/****** TEE AES mode *****/ +typedef enum { + TEE_AES_MODE_ECB = 0, ///< TEE AES ECB mode + TEE_AES_MODE_CBC = 1, ///< TEE AES CBC mode + TEE_AES_MODE_MAX, ///< invaild mode +} +tee_aes_mode_e; + +/** + \brief TEE AES encrypt + \note Length should be a multiple of the block size (16 bytes) + After calling this function, the content of iv is updated. + \param[in] in Pointer to plaintext buffer + \param[in] in_len Plaintext buffer length + \param[in] key Pointer to secret key + \param[in] key_len Secret key size,must be 16 bytes for AES128,24 bytes for AES192 or 32byes for AES256 + \param[out] out Pointer to ciphertext buffer + \param[in] mode \ref tee_aes_mode_e + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_aes_encrypt(const uint8_t *in, uint32_t in_len, + const uint8_t *key, uint32_t key_len, + uint8_t iv[16], + uint8_t *out, + tee_aes_mode_e mode); + +/** + \brief TEE AES decrypt + \note Length should be a multiple of the block size (16 bytes) + After calling this function, the content of iv is updated. + \param[in] in Pointer to ciphertext buffer + \param[in] in_len Ciphertext buffer length + \param[in] key Pointer to secret key + \param[in] key_len Secret key size,must be 16 bytes for AES128,24 bytes for AES192 or 32byes for AES256 + \param[out] out Pointer to plaintext buffer + \param[in] mode \ref tee_aes_mode_e + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_aes_decrypt(const uint8_t *in, uint32_t in_len, + const uint8_t *key, uint32_t key_len, + uint8_t iv[16], + uint8_t *out, + uint32_t mode); + +/** + \brief TEE AES ECB encrypt + \note Length should be a multiple of the block size (16 bytes) + After calling this function, the content of iv is updated. + \param[in] in Pointer to plaintext buffer + \param[in] in_len Plaintext buffer length + \param[in] key Pointer to secret key + \param[in] key_len Secret key size,must be 16 bytes for AES128,24 bytes for AES192 or 32byes for AES256 + \param[out] out Pointer to ciphertext buffer + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_aes_encrypt_ecb(in, in_len, key, key_len, out) \ + csi_tee_aes_encrypt(in, in_len, key, key_len, NULL, out, TEE_AES_MODE_ECB) + +/** + \brief TEE AES ECB decrypt + \note Length should be a multiple of the block size (16 bytes) + After calling this function, the content of iv is updated. + \param[in] in Pointer to ciphertext buffer + \param[in] in_len Ciphertext buffer length + \param[in] key Pointer to secret key + \param[in] key_len Secret key size,must be 16 bytes for AES128,24 bytes for AES192 or 32byes for AES256 + \param[out] out Pointer to plaintext buffer + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_aes_decrypt_ecb(in, in_len, key, key_len, out) \ + csi_tee_aes_decrypt(in, in_len, key, key_len, NULL, out, TEE_AES_MODE_ECB) + +/** + \brief TEE AES CBC encrypt + \note Length should be a multiple of the block size (16 bytes) + After calling this function, the content of iv is updated. + \param[in] in Pointer to ciphertext buffer + \param[in] in_len Ciphertext buffer length + \param[in] key Pointer to secret key + \param[in] key_len Secret key size,must be 16 bytes for AES128,24 bytes for AES192 or 32byes for AES256 + \param[out] out Pointer to plaintext buffer + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_aes_encrypt_cbc(in, in_len, key, key_len, iv, out) \ + csi_tee_aes_encrypt(in, in_len, key, key_len, iv, out, TEE_AES_MODE_CBC) + +/** + \brief TEE AES CBC decrypt + \note Length should be a multiple of the block size (16 bytes) + After calling this function, the content of iv is updated. + \param[in] in Pointer to ciphertext buffer + \param[in] in_len Ciphertext buffer length + \param[in] key Pointer to secret key + \param[in] key_len Secret key size,must be 16 bytes for AES128,24 bytes for AES192 or 32byes for AES256 + \param[out] out Pointer to plaintext buffer + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_aes_decrypt_cbc(in, in_len, key, key_len, iv, out) \ + csi_tee_aes_decrypt(in, in_len, key, key_len, iv, out, TEE_AES_MODE_CBC) + +/** + \brief TEE BASE64 encode/decode + \param[in] in Pointer to input data buffer + \param[in] in_len Input data buffer length + \param[out] out Pointer to output data buffer + \param[out] out_len Output data buffer length + \param[in] is_encode 1 encode 0 decode + \param[in] wsafe Base64 websafe feature,set 1, replace "+/" with "-_" + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_base64(const uint8_t *in, uint32_t in_len, + uint8_t *out, uint32_t *out_len, + uint32_t is_encode, + uint32_t wsafe); + +/** + \brief TEE BASE64 encode + \param[in] in Pointer to input data buffer + \param[in] in_len Input data buffer length + \param[out] out Pointer to output data buffer + \param[out] out_len Output data buffer length + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_base64_encode(in,in_len,out,out_len) \ + csi_tee_base64(in,in_len,out,out_len,1,0) + +/** + \brief TEE BASE64 decode + \param[in] in Pointer to input data buffer + \param[in] in_len Input data buffer length + \param[out] out Pointer to output data buffer + \param[out] out_len Output data buffer length + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_base64_decode(in,in_len,out,out_len) \ + csi_tee_base64(in,in_len,out,out_len,0,0) + +/** + \brief TEE BASE64 web safe encode + \param[in] in Pointer to input data buffer + \param[in] in_len Input data buffer length + \param[out] out Pointer to output data buffer + \param[out] out_len Output data buffer length + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_base64_websafe_encode(in,in_len,out,out_len) \ + csi_tee_base64(in,in_len,out,out_len,1,1) + +/** + \brief TEE BASE64 web safe decode + \param[in] in Pointer to input data buffer + \param[in] in_len Input data buffer length + \param[out] out Pointer to output data buffer + \param[out] out_len Output data buffer length + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_base64_websafe_decode(in,in_len,out,out_len) \ + csi_tee_base64(in,in_len,out,out_len,0,1) + +/** + \brief TEE obtain CID from Key Provisioning + \param[out] out Pointer to cid buffer + \param[out] out_len CID buffer length,if cid obtain successfully, + out_len is updated to actual cid sizes + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_get_cid(uint8_t *out, uint32_t *out_len); + +/****** lpm mode *****/ +typedef enum { + TEE_LPM_MODE_WAIT = 0, ///< lpm wait + TEE_LPM_MODE_DOZE = 1, ///< lpm doze + TEE_LPM_MODE_STOP = 2, ///< lpm stop + TEE_LPM_MODE_STANDBY = 3, ///< lpm standby + TEE_LPM_MODE_CLOCK = 4, ///< lpm clock gate + TEE_LPM_MODE_MAX, +} tee_lpm_mode_e; + +/** + \brief TEE set low power mode + \param[in] gate Not use for now + \param[in] irqid Not use for now + \param[in] mode \ref tee_lpm_mode_e + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_enter_lpm(uint32_t gate, uint32_t irqid, tee_lpm_mode_e mode); + +/** + \brief TEE obtain manifest info from manifest table + \note call csi_tee_get_sys_img_info, csi_tee_get_sys_os_version or csi_tee_get_sys_partition is better + \param[out] out Pointer to info buffer + \param[out] out_len Info buffer length,if info obtain successfully, + out_len is updated to actual sizes + \param[in] name info name + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_get_manifest_info(uint8_t *out, uint32_t *out_len, char *name); + +/** + \brief TEE obtain image buffer from manifest table + \param[out] out Pointer to image buffer + \param[out] out_len Image buffer length,if info obtain successfully, + out_len is updated to actual image buffer sizes + \param[in] img_name Image name + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_get_sys_img_info(out,out_len,img_name) \ + csi_tee_get_manifest_info(out,out_len,img_name) + +/** + \brief TEE obtain os version from manifest table + \param[out] out Pointer to os version buffer + \param[out] out_len OS version buffer length,if info obtain successfully, + out_len is updated to actual os version buffer sizes + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_get_sys_os_version(out,out_len) \ + csi_tee_get_manifest_info(out,out_len,"os_v") + +/** + \brief TEE obtain partition buffer from manifest table + \param[out] out Pointer to partition buffer + \param[out] out_len Partition buffer length,if info obtain successfully, + out_len is updated to actual partition buffer sizes + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_get_sys_partition(out,out_len) \ + csi_tee_get_manifest_info(out,out_len,"sys_p") + +/** + \brief TEE set random seed + \param[in] Seed random sedd + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_rand_seed(uint32_t seed); + +/** + \brief TEE ramdom date generation + \param[out] out Pointer to random data buffer + \param[in] out_len Data buffer length + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_rand_generate(uint8_t *out, uint32_t out_len); + +/****** TEE RSA sign type *****/ +typedef enum { + TEE_RSA_MD5 = 0, ///< MD5 + TEE_RSA_SHA1 = 1, ///< SHA1 + TEE_RSA_SHA256 = 3, ///< SHA256 + TEE_RSA_SIGN_TYPE_MAX, ///< invailed type +} tee_rsa_sign_type_e; + +/** + \brief TEE RSA sign with private key + \param[in] in Pointer to digest buffer + \param[in] in_len Digest buffer length + \param[in] key Pointer to private key,key contains n, e, d + \param[in] key_len Private key size,must be 128*3 = 384 bytes for RSA1024, 256*3 = 768 bytes for RSA2048 + \param[out] sign Pointer to sign buffer + \param[out] sign_len Sign buffer length + \param[in] type \ref tee_rsa_sign_type_e + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_rsa_sign(const uint8_t *in, uint32_t in_len, + const uint8_t *key, uint32_t key_len, + uint8_t *sign, uint32_t *sign_len, + tee_rsa_sign_type_e type); + +/** + \brief TEE RSA verify with public key + \param[in] in Pointer to digest buffer + \param[in] in_len Digest buffer length + \param[in] key Pointer to public key,key contains n, e + \param[in] key_len Public key size,must be 128*2 = 256 bytes for RSA1024, 256*2 = 512 bytes for RSA2048 + \param[in] sign Pointer to sign buffer + \param[in] sign_len Sign buffer length + \param[in] type \ref tee_rsa_sign_type_e + \return Return 0 if verify successful,otherwise error code +*/ +int32_t csi_tee_rsa_verify(const uint8_t *in, uint32_t in_len, + const uint8_t *key, uint32_t key_len, + uint8_t *sign, uint32_t sign_len, + tee_rsa_sign_type_e type); + +/****** TEE RSA padding mode *****/ +typedef enum { + TEE_RSA_PKCS1_PADDING = 0x01, ///< RSA PKCS padding mode + TEE_RSA_NO_PADDING = 0x02, ///< RSA no padding mode +} tee_rsa_padding_mode_e; + +/** + \brief TEE RSA encrypt with public key + \param[in] in Pointer to plaintext buffer + \param[in] in_len Plaintext buffer length + \param[in] key Pointer to public key,key contains n, e + \param[in] key_len Public key size, must be 128*2 = 256 bytes for RSA1024, 256*2 = 512 bytes for RSA2048 + \param[in] out Pointer to ciphertext buffer + \param[in] out_len Ciphertext buffer length + \param[in] padding \ref tee_rsa_padding_mode_e + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_rsa_encrypt(const uint8_t *in, uint32_t in_len, + const uint8_t *key, uint32_t key_len, + uint8_t *out, uint32_t *out_len, + tee_rsa_padding_mode_e padding); +/** + \brief TEE RSA decrypt with private key + \param[in] in Pointer to ciphertext buffer + \param[in] in_len Ciphertext buffer length + \param[in] key Pointer to private key,key contains n, e, d + \param[in] key_len Private key size,must be 128*3 = 384 bytes for RSA1024, 256*3 = 768 bytes for RSA2048 + \param[in] out Pointer to plaintext buffer + \param[in] out_len Plaintext buffer length + \param[in] padding \ref tee_rsa_padding_mode_e + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_rsa_decrypt(const uint8_t *in, uint32_t in_len, + const uint8_t *key, uint32_t key_len, + uint8_t *out, uint32_t *out_len, + tee_rsa_padding_mode_e padding); + +/** + \brief TEE RSA sign with internal private key + \note Only use if key provisioning exist + \param[in] in Pointer to digest buffer + \param[in] in_len Digest buffer length + \param[out] sign Pointer to sign buffer + \param[out] sign_len Sign buffer length + \param[in] type \ref tee_rsa_sign_type_e + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_cid_rsa_sign(in,in_len,sign,sign_len,type) \ + csi_tee_rsa_sign(in,in_len,NULL,0,sign,sign_len,type) + +/** + \brief TEE RSA verify with internal public key + \note Only use if key provisioning exist + \param[in] in Pointer to digest buffer + \param[in] in_len Digest buffer length + \param[in] sign Pointer to sign buffer + \param[in] sign_len Sign buffer length + \param[in] type \ref tee_rsa_sign_type_e + \return Return 0 if verify successful,otherwise error code +*/ +#define csi_tee_cid_rsa_verify(in,in_len,sign,sign_len,type) \ + csi_tee_rsa_verify(in,in_len,NULL,0,sign,sign_len,type) + +/** + \brief TEE RSA encrypt with internal public key + \note Only use if key provisioning exist + \param[in] in Pointer to plaintext buffer + \param[in] in_len Plaintext buffer length + \param[in] out Pointer to ciphertext buffer + \param[in] out_len Ciphertext buffer length + \param[in] padding \ref tee_rsa_padding_mode_e + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_cid_rsa_encrypt(in,in_len,out,out_len,padding) \ + csi_tee_rsa_encrypt(in,in_len,NULL,0,out,out_len,padding) + +/** + \brief TEE RSA decrypt with internal private key + \note Only use if key provisioning exist + \param[in] in Pointer to ciphertext buffer + \param[in] in_len Ciphertext buffer length + \param[in] key Pointer to private key,key contains n, e, d + \param[in] key_len Private key size,must be 128*3 = 384 bytes for RSA1024, 256*3 = 768 bytes for RSA2048 + \param[in] out Pointer to plaintext buffer + \param[in] out_len Plaintext buffer length + \param[in] padding \ref tee_rsa_padding_mode_e + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_cid_rsa_decrypt(in,in_len,out,out_len,padding) \ + csi_tee_rsa_decrypt(in,in_len,NULL,0,out,out_len,padding) + +/** + \brief verify boot image with boot public key + \note Only use if key provisioning exist + \param[in] in Pointer to digest buffer + \param[in] in_len Digest buffer length + \param[in] sign Pointer to sign buffer + \param[in] sign_len Sign buffer length + \param[in] type \ref tee_rsa_sign_type_e + \return Return 0 if verify successful,otherwise error code +*/ +int32_t csi_tee_img_rsa_verify(const uint8_t *in, uint32_t in_len, + uint8_t *sign, uint32_t sign_len, + tee_rsa_sign_type_e type); + +/****** TEE HASH operation mode *****/ +typedef enum { + TEE_HASH_OP_NONE = 0, ///< No operation + TEE_HASH_OP_START = 1, ///< HASH init + TEE_HASH_OP_UPDATA = 2, ///< HASH update + TEE_HASH_OP_FINISH = 3, ///< HASH finish + TEE_HASH_OP_MAX, ///< invailed operation +} tee_hash_op_e; + +/****** TEE HMAC type *****/ +typedef enum { + TEE_HMAC_SHA1 = 1, ///< HMAC with SHA1 +} tee_hmac_type_e; + +/** + \brief TEE HAMC + \note Call csi_tee_hmac_digest is better + out buffer size must be large enough according to type, eg. 20 bytes for TEE_HMAC_SHA1 + \param[in] in Pointer to input data buffer + \param[in] in_len Input data buffer length + \param[in] key Pointer to key buffer + \param[in] key_len Key buffer size + \param[out] out Pointer to output date buffer + \param[in] type \ref tee_hmac_type_e + \param[in] hash_op \ref tee_hash_op_e + \param[in] ctx Pointer to context of hmac + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_hmac(const uint8_t *in, uint32_t in_len, + const uint8_t *key, uint32_t key_len, + uint8_t *out, + tee_hmac_type_e type, + tee_hash_op_e hash_op, + uint32_t *ctx); + +/** + \brief TEE HAMC digest + \note out buffer size must be large enough according to type, eg. 20 bytes for TEE_HMAC_SHA1 + \param[in] in Pointer to input data buffer + \param[in] in_len Input data buffer length + \param[in] key Pointer to key buffer + \param[in] key_len Key buffer size + \param[out] out Pointer to output date buffer + \param[in] type \ref tee_hmac_type_e + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_hmac_digest(in,in_len,key,key_len,out,type) \ + csi_tee_hmac(in,in_len,key,key_len,out,type,TEE_HASH_OP_NONE,NULL) + +/****** TEE SHA type *****/ +typedef enum { + TEE_SHA1 = 0, ///< SHA1 + TEE_SHA256 = 1, ///< SHA256 + TEE_SHA224 = 2, ///< SHA224 + TEE_SHA384 = 3, ///< SHA384 + TEE_SHA512 = 4, ///< SHA512 + TEE_SHA_MAX, ///< invaild sha type +} tee_sha_type_t; + +/** + \brief TEE SHA + \note Call csi_tee_sha_digest, csi_tee_sha_start, csi_tee_sha_update or csi_tee_sha_finish is better + out buffer size must be large enough according to type, eg. 20 bytes for TEE_SHA1, 32 bytes for TEE_SHA256 + \param[in] in Pointer to input data buffer + \param[in] in_len Input data buffer length + \param[out] out Pointer to output date buffer + \param[in] type \ref tee_sha_type_t + \param[in] hash_op \ref tee_hash_op_e + \param[in] ctx Pointer to context of sha + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_sha(const uint8_t *in, uint32_t in_len, + uint8_t *out, + tee_sha_type_t type, + tee_hash_op_e hash_op, + void *ctx); + +/** + \brief TEE SHA digest + \note out buffer size must be large enough according to type, eg. 20 bytes for TEE_SHA1, 32 bytes for TEE_SHA256 + \param[in] in Pointer to input data buffer + \param[in] in_len Input data buffer length + \param[out] out Pointer to output date buffer + \param[in] type \ref tee_sha_type_t + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_sha_digest(in,in_len,out,type) \ + csi_tee_sha(in,in_len,out,type,TEE_HASH_OP_NONE,NULL); + +/** + \brief TEE SHA start, initial sha + \param[in] type \ref tee_sha_type_t + \param[in] ctx Pointer to context of sha + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_sha_start(type,ctx) \ + csi_tee_sha(NULL,0,NULL,type,TEE_HASH_OP_START,ctx); + +/** + \brief TEE SHA update, update data + \param[in] in Pointer to input data buffer + \param[in] in_len Input data buffer length + \param[in] ctx Pointer to context of sha + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_sha_update(in,in_len,ctx) \ + csi_tee_sha(in,in_len,NULL,0,TEE_HASH_OP_UPDATA,ctx); + +/** + \brief TEE SHA digest, get sha digest + \note out buffer size must be large enough according to type, eg. 20 bytes for TEE_SHA1, 32 bytes for TEE_SHA256 + \param[out] out Pointer to output date buffer + \param[in] ctx Pointer to context of sha + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_sha_finish(out,ctx) \ + csi_tee_sha(NULL,0,out,0,TEE_HASH_OP_FINISH,ctx); + +/** + \brief TEE get device name and product key + \param[in] name_encrypted Pointer to device name ciphertext + \param[in] name_encrypted_len device name ciphertext length + \param[in] product_key_encrypted Pointer to device product key ciphertext + \param[in] product_key_encrypted_len Device product key ciphertext length + \param[out] name Pointer to device name + \param[out] name_len Device name length + \param[out] product_key Pointer to device product key + \param[out] product_key_len Device product key length + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_dev_info_get(const uint8_t *name_encrypted, uint32_t name_encrypted_len, + const uint8_t *product_key_encrypted, uint32_t product_key_encrypted_len, + const uint8_t *name, uint32_t *name_len, + const uint8_t *product_key, uint32_t *product_key_len); + +/** + \brief TEE device info sign + \param[in] in Pointer to input date buffer + \param[in] in_len Input data buffer length + \param[in] device_secret Pointer to device secret ciphertext + \param[in] device_secret_len Device secret ciphertext length + \param[out] sign Pointer to signed buffer + \param[out] sign_len Signed buffer length + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_dev_info_sign(const uint8_t *in, uint32_t in_len, + const uint8_t *device_secret, uint32_t device_secret_len, + const uint8_t *sign, uint32_t *sign_len); + +/** + \brief TEE device info encrypt/decrypt + \param[in] in Pointer to input date buffer + \param[in] in_len Input data buffer length + \param[in] out Pointer to output date buffer + \param[in] out_len Onput data buffer length + \param[in] is_enc 1 incrypt 0 decrypt + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_dev_info_crypt(const uint8_t *in, uint32_t in_len, + uint8_t *out, uint32_t *out_len, + uint8_t is_enc); + +/** + \brief TEE device info encrypt + \param[in] in Pointer to input date buffer + \param[in] in_len Input data buffer length + \param[in] out Pointer to output date buffer + \param[in] out_len Onput data buffer length + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_dev_info_encrypt(in, in_len, out, out_len) \ + csi_tee_dev_info_crypt(in, in_len, out, out_len, 1) + +/** + \brief TEE device info decrypt + \param[in] in Pointer to input date buffer + \param[in] in_len Input data buffer length + \param[in] out Pointer to output date buffer + \param[in] out_len Onput data buffer length + \return Return 0 if successful,otherwise error code +*/ +#define csi_tee_dev_info_decrypt(in, in_len, out, out_len) \ + csi_tee_dev_info_crypt(in, in_len, out, out_len, 0) + +/** + \brief Set system frequence + \param[in] clk_src Indicate clock source type + \param[in] clk_val System freqence to be set + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_set_sys_freq(uint32_t clk_src, uint32_t clk_val); + +/** + \brief Get system frequence + \param[in] clk_val Value address to store system freqence + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_get_sys_freq(uint32_t *clk_val); + +/** + \brief Read system register + \param[in] addr Indicate register address + \param[out] val Value to read from the address + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_read_reg(uint32_t addr, uint32_t *val); + +/** + \brief Wrte system register + \param[in] addr Indicate register address + \param[in] val Value to be written into the address + \return Return 0 if successful,otherwise error code +*/ +int32_t csi_tee_write_reg(uint32_t addr, uint32_t val); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_TEE_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tick.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tick.h new file mode 100644 index 00000000000..8f06dc33448 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tick.h @@ -0,0 +1,79 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file tick.h + * @brief Header File for TICK Driver + * @version V1.0 + * @date 28. Sep 2020 + ******************************************************************************/ + +#ifndef _DRV_TICK_H_ +#define _DRV_TICK_H_ + +#include +#include +#include + +#ifndef CONFIG_SYSTICK_HZ +#define CONFIG_SYSTICK_HZ 100U +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + \brief Initializes the resources needed for the TICK interface + \return error code \ref csi_error_t +*/ +csi_error_t csi_tick_init(void); + +/** + \brief De-initialize TICK Interface +*/ +void csi_tick_uninit(void); + +/** + \brief Get the sys-tick, one tick == (1000 / CONFIG_SYSTICK_HZ) ms + \return the sys-tick +*/ +uint32_t csi_tick_get(void); + +/** + \brief Get the time which start from csi_tick_init + \return The time which start from csi_tick_init (ms) +*/ +uint32_t csi_tick_get_ms(void); + +/** + \brief Get the time which start from csi_tick_init + \return The time which start from csi_tick_init (us) +*/ +uint64_t csi_tick_get_us(void); + +/** + \brief Increase the sys-tick +*/ +void csi_tick_increase(void); + +#ifdef __cplusplus +} +#endif + +#endif /*_DRV_TICK_H_*/ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/timer.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/timer.h new file mode 100644 index 00000000000..9f1039c13da --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/timer.h @@ -0,0 +1,132 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/timer.h + * @brief Header File for TIMER Driver + * @version V1.0 + * @date 9. Oct 2020 + * @model timer + ******************************************************************************/ + +#ifndef _DRV_TIMER_H_ +#define _DRV_TIMER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct csi_timer csi_timer_t; + +struct csi_timer { + csi_dev_t dev; + void (*callback)(csi_timer_t *timer, void *arg); + void *arg; + void *priv; +}; + +/** + \brief Initialize TIMER interface. initializes the resources needed for the TIMER interface + \param[in] timer Handle to operate + \param[in] idx TIMER index + \return Error code \ref csi_error_t +*/ +csi_error_t csi_timer_init(csi_timer_t *timer, uint32_t idx); + +/** + \brief De-initialize TIMER interface. stops operation and releases the software resources used by the interface + \param[in] timer Handle to operate + \return None +*/ +void csi_timer_uninit(csi_timer_t *timer); + +/** + \brief Start TIMER + \param[in] timer Handle to operate + \param[in] timeout_us The timeout for TIMER + \return Error code \ref csi_error_t +*/ +csi_error_t csi_timer_start(csi_timer_t *timer, uint32_t timeout_us); + +/** + \brief Stop TIMER + \param[in] timer Handle to operate + \return None +*/ +void csi_timer_stop(csi_timer_t *timer); + +/** + \brief Get TIMER remaining value + \param[in] timer Handle to operate + \return remaining value +*/ +uint32_t csi_timer_get_remaining_value(csi_timer_t *timer); + +/** + \brief Get TIMER load value + \param[in] timer Handle to operate + \return Load value +*/ +uint32_t csi_timer_get_load_value(csi_timer_t *timer); + +/** + \brief Check TIMER is running + \param[in] timer Handle to operate + \return + true - TIMER is running + false - TIMER is stopped +*/ +bool csi_timer_is_running(csi_timer_t *timer); + +/** + \brief Attach the callback handler to TIMER + \param[in] timer Operate handle + \param[in] callback Callback function + \param[in] arg Callback's param + \return Error code \ref csi_error_t +*/ +csi_error_t csi_timer_attach_callback(csi_timer_t *timer, void *callback, void *arg); + +/** + \brief Detach the callback handler + \param[in] timer Operate handle + \return None +*/ +void csi_timer_detach_callback(csi_timer_t *timer); + +/** + \brief Enable TIMER power manage + \param[in] timer Handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_timer_enable_pm(csi_timer_t *timer); + +/** + \brief Disable TIMER power manage + \param[in] timer Handle to operate + \return None +*/ +void csi_timer_disable_pm(csi_timer_t *timer); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_TIMER_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tipc.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tipc.h new file mode 100644 index 00000000000..da117ebcb95 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/tipc.h @@ -0,0 +1,56 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/tipc.h + * @brief Header File for TIPC Driver + * @version V1.0 + * @date 08. Mar 2020 + * @model tipc + ******************************************************************************/ + +#ifndef _DRV_TIPC_H_ +#define _DRV_TIPC_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t ip; + uint16_t dev_tag; + uint8_t idx; +} csi_tipcmap_t; + +/** + \brief Config the tipc module properity + \param[in] dev Dev handle \ref csi_dev_t + \param[in] is_secure is secure or not +*/ +csi_error_t csi_dev_secure_config(csi_dev_t *dev, bool is_secure); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_TIPC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/uart.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/uart.h new file mode 100644 index 00000000000..20ecc29dedd --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/uart.h @@ -0,0 +1,241 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/uart.h + * @brief Header File for UART Driver + * @version V1.0 + * @date 08. Apr 2020 + * @model uart + ******************************************************************************/ + +#ifndef _DRV_UART_H_ +#define _DRV_UART_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*----- UART Control Codes: Mode Parameters: Data Bits -----*/ +typedef enum { + UART_DATA_BITS_5 = 0, ///< 5 Data bits + UART_DATA_BITS_6, ///< 6 Data bit + UART_DATA_BITS_7, ///< 7 Data bits + UART_DATA_BITS_8, ///< 8 Data bits (default) + UART_DATA_BITS_9 ///< 9 Data bits +} csi_uart_data_bits_t; + +/*----- UART Control Codes: Mode Parameters: Parity -----*/ +typedef enum { + UART_PARITY_NONE = 0, ///< No Parity (default) + UART_PARITY_EVEN, ///< Even Parity + UART_PARITY_ODD, ///< Odd Parity +} csi_uart_parity_t; + +/*----- UART Control Codes: Mode Parameters: Stop Bits -----*/ +typedef enum { + UART_STOP_BITS_1 = 0, ///< 1 Stop bit (default) + UART_STOP_BITS_2, ///< 2 Stop bits + UART_STOP_BITS_1_5, ///< 1.5 Stop bits +} csi_uart_stop_bits_t; + +/*----- UART Control Codes: Mode Parameters: Flow Control -----*/ +typedef enum { + UART_FLOWCTRL_NONE = 0, ///< none flowctrl + UART_FLOWCTRL_RTS, ///< RTS + UART_FLOWCTRL_CTS, ///< CTS + UART_FLOWCTRL_RTS_CTS ///< RTS & CTS +} csi_uart_flowctrl_t; + +/****** UART Event *****/ +typedef enum { + UART_EVENT_SEND_COMPLETE = 0, ///< Send data completed. + UART_EVENT_RECEIVE_COMPLETE, ///< Receive data completed. + UART_EVENT_RECEIVE_FIFO_READABLE, ///< Data in uart fifo, call csi_uart_receive() get the data. + UART_ENENT_BREAK_INTR, ///< the serial input,sin, is held in a logic '0' state for longer than the sum of start time+data bits+parity+stop bits. + UART_EVENT_ERROR_OVERFLOW, ///< A new data character was received before the previous data was read. + UART_EVENT_ERROR_PARITY, ///< Occur parity error in the receiver. + UART_EVENT_ERROR_FRAMING ///< the receiver does not detect a valid STOP bit in the received data. +} csi_uart_event_t; + +///< definition for uart. +typedef struct csi_uart csi_uart_t; + +struct csi_uart { + csi_dev_t dev; + void (*callback)(csi_uart_t *uart, csi_uart_event_t event, void *arg); + void *arg; + uint8_t *tx_data; + uint32_t tx_size; + uint8_t *rx_data; + uint32_t rx_size; + csi_dma_ch_t *tx_dma; + csi_dma_ch_t *rx_dma; + csi_error_t (*send)(csi_uart_t *uart, const void *data, uint32_t size); + csi_error_t (*receive)(csi_uart_t *uart, void *data, uint32_t size); + csi_state_t state; + void *priv; +}; + +/** + \brief Initializes the resources needed for the UART interface. + \param[in] uart Operate handle. + \param[in] idx The device idx. + \return Error code. +*/ +csi_error_t csi_uart_init(csi_uart_t *uart, uint32_t idx); + +/** + \brief De-initialize UART Interface. stops operation and releases the software resources used by the interface. + \param[in] uart Operate handle. + \return Error code. +*/ +void csi_uart_uninit(csi_uart_t *uart); + +/** + \brief Attach the callback handler to UART. + \param[in] uart Operate handle. + \param[in] callback Callback function. + \param[in] arg User can define it by himself as callback's param. + \return Error code. +*/ +csi_error_t csi_uart_attach_callback(csi_uart_t *uart, void *callback, void *arg); + +/** + \brief Detach the callback handler. + \param[in] uart Operate handle. +*/ +void csi_uart_detach_callback(csi_uart_t *uart); + +/** + \brief Config the baudrate. + \param[in] uart UART handle to operate. + \param[in] baud UART baudrate. + \return Error code. +*/ +csi_error_t csi_uart_baud(csi_uart_t *uart, uint32_t baud); + +/** + \brief Config the uart format. + \param[in] uart UART handle to operate. + \param[in] data_bit UART data bits. + \param[in] parity UART data parity. + \param[in] stop_bit UART stop bits. + \return Error code. +*/ +csi_error_t csi_uart_format(csi_uart_t *uart, csi_uart_data_bits_t data_bits, + csi_uart_parity_t parity, csi_uart_stop_bits_t stop_bits); + +/** + \brief Config the uart flow control. + \param[in] uart UART handle to operate. + \param[in] flowctrl UART flow control. + \return Error code. +*/ +csi_error_t csi_uart_flowctrl(csi_uart_t *uart, csi_uart_flowctrl_t flowctrl); + +/** + \brief Start send data to UART transmitter, this function is blocking. + \param[in] uart UART handle to operate. + \param[in] data Pointer to buffer with data to send to UART transmitter. + \param[in] size Number of data to send (byte). + \param[in] timeout The timeout between bytes(ms). + \return the num of data which is sent successfully or CSI_ERROR. +*/ +int32_t csi_uart_send(csi_uart_t *uart, const void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start send data to UART transmitter, this function is non-blocking. + \param[in] uart UART handle to operate. + \param[in] data Pointer to buffer with data to send to UART transmitter. + \param[in] size Number of data to send (byte). + \return Error code. +*/ +csi_error_t csi_uart_send_async(csi_uart_t *uart, const void *data, uint32_t size); + +/** + \brief Query data from UART receiver FIFO, this function is blocking. + \param[in] uart UART handle to operate. + \param[out] data Pointer to buffer for data to receive from UART receiver. + \param[in] size Number of data to receive. + \param[in] timeout The timeout between bytes(ms). + \return the num of data witch is received successfully or CSI_ERROR. +*/ +int32_t csi_uart_receive(csi_uart_t *uart, void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start receiving data from UART receiver, this function is non-blocking. + \param[in] uart UART handle to operate. + \param[out] data Pointer to buffer for data to receive from UART receiver. + \param[in] size Number of data to receive (byte). + \return Error code. +*/ +csi_error_t csi_uart_receive_async(csi_uart_t *uart, void *data, uint32_t size); + +/** + \brief Get character in query mode. + \param[in] uart UART handle to operate. + \return the character to get. +*/ +uint8_t csi_uart_getc(csi_uart_t *uart); + +/** + \brief Send character in query mode. + \param[in] uart UART handle to operate. + \param[in] ch The character to be send. +*/ +void csi_uart_putc(csi_uart_t *uart, uint8_t ch); + +/** + \brief Link DMA channel to uart device. + \param[in] uart UART handle to operate. + \param[in] tx_dma The DMA channel handle for send, when it is NULL means to unlink the channel. + \param[in] rx_dma The DMA channel handle for receive, when it is NULL means to unlink the channel. + \return Error code. +*/ +csi_error_t csi_uart_link_dma(csi_uart_t *uart, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma); + +/** + \brief Get the state of uart device. + \param[in] uart UART handle to operate. + \param[out] state The state of uart device. + \return Error code. +*/ +csi_error_t csi_uart_get_state(csi_uart_t *uart, csi_state_t *state); + +/** + \brief Enable uart power manage. + \param[in] uart UART handle to operate. + \return Error code. +*/ +csi_error_t csi_uart_enable_pm(csi_uart_t *uart); + +/** + \brief Disable uart power manage. + \param[in] uart UART handle to operate. +*/ +void csi_uart_disable_pm(csi_uart_t *uart); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_UART_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi.h new file mode 100644 index 00000000000..8e8cb1d305d --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi.h @@ -0,0 +1,42 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/usi.h + * @brief Header File for USI Driver + * @version V1.0 + * @date 02. June 2020 + * @model usi + ******************************************************************************/ + +#ifndef _DRV_USI_H_ +#define _DRV_USI_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_USI_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_iic.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_iic.h new file mode 100644 index 00000000000..257b534aa95 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_iic.h @@ -0,0 +1,260 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/drv_usi_iic.h + * @brief Header File for IIC driver + * @version V1.0 + * @date 02. June 2020 + * @model usi_iic + ******************************************************************************/ + +#ifndef _DRV_USI_IIC_H_ +#define _DRV_USI_IIC_H_ + +#include +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + \brief Init iic ctrl block. + Initializes the resources needed for the iic instance. + \param[in] iic Handle of iic instance. + \param[in] idx Index of instance. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_init(csi_iic_t *iic, uint32_t idx); + +/** + \brief Uninit iic ctrl block. + Stops operation and releases the software resources used by the instance. + \param[in] iic Handle of iic instance. +*/ +void csi_usi_iic_uninit(csi_iic_t *iic); + +/** + \brief Config iic master or slave mode. + \param[in] iic Handle of iic instance. + \param[in] mode IIC mode \ref csi_iic_mode_t. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_mode(csi_iic_t *iic, csi_iic_mode_t mode); + +/** + \brief Config iic addr mode. + \param[in] iic Handle of iic instance. + \param[in] addr_mode IIC addr mode \ref csi_iic_addr_mode_t. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_addr_mode(csi_iic_t *iic, csi_iic_addr_mode_t addr_mode); + +/** + \brief Config iic speed. + \param[in] iic Handle of iic instance. + \param[in] speed iic speed mode \ref csi_iic_speed_t. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_speed(csi_iic_t *iic, csi_iic_speed_t speed); + +/** + \brief Config iic own addr. + \param[in] iic Handle of iic instance. + \param[in] own_addr IIC set own addr at slave mode. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_own_addr(csi_iic_t *iic, uint32_t own_addr); + +/** + \brief Start sending data as iic master. + This function is blocking. + \param[in] iic Handle of iic instance. + \param[in] devaddr Addrress of slave device. + \param[in] data Pointer to send data buffer. + \param[in] size Size of data items to send. + \param[in] timout Unit of time delay(ms). + \return The amount of real data sent. +*/ +int32_t csi_usi_iic_master_send(csi_iic_t *iic, uint32_t devaddr, const void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start receiving data as iic master. + This function is blocking. + \param[in] iic Handle to operate. + \param[in] devaddr IIC addrress of slave device. + \param[out] data Pointer to buffer for data to receive from iic receiver. + \param[in] size Size of data items to receive. + \param[in] timeout Unit of time delay(ms). + \return The amount of real data received. +*/ +int32_t csi_usi_iic_master_receive(csi_iic_t *iic, uint32_t devaddr, void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start sending data as iic master. + This function is non-blocking,\ref csi_usi_iic_event_t is signaled when transfer completes or error happens. + \param[in] iic Handle to operate. + \param[in] devaddr IIC addrress of slave device. + \param[in] data Pointer to send data buffer. + \param[in] size Size of data items to send. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_master_send_async(csi_iic_t *iic, uint32_t devaddr, const void *data, uint32_t size); + +/** + \brief Start receiving data as iic master. + This function is non-blocking.\ref csi_usi_iic_event_t is signaled when transfer completes or error happens. + \param[in] iic Handle to operate. + \param[in] devaddr IIC addrress of slave device. + \param[out] data Pointer to buffer for data to receive from iic receiver. + \param[in] size Size of data items to receive. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_master_receive_async(csi_iic_t *iic, uint32_t devaddr, void *data, uint32_t size); + +/** + \brief Start sending data as iic master. + This function is blocking. + \param[in] iic Handle of iic instance. + \param[in] devaddr Addrress of slave device. + \param[in] memaddr Internal addr of device. + \param[in] memaddr_size Internal addr mode of device. + \param[in] data Pointer to send data buffer. + \param[in] size Size of data items to send. + \param[in] timout Unit of time delay(ms). + \return The amount of real data sent. +*/ +int32_t csi_usi_iic_mem_send(csi_iic_t *iic, uint32_t devaddr, uint16_t memaddr, csi_iic_mem_addr_size_t memaddr_size, const void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start receiving data as iic master. + This function is blocking. + \param[in] iic Handle to operate. + \param[in] devaddr IIC addrress of slave device. + \param[in] memaddr Internal addr of device. + \param[in] memaddr_mode Internal addr mode of device. + \param[out] data Pointer to buffer for data to receive from eeprom device. + \param[in] size Size of data items to receive. + \param[in] timeout Unit of time delay(ms). + \return The amount of real data received. +*/ +int32_t csi_usi_iic_mem_receive(csi_iic_t *iic, uint32_t devaddr, uint16_t memaddr, csi_iic_mem_addr_size_t memaddr_size, void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start sending data as iic slave. + This function is blocking. + \param[in] iic Handle to operate. + \param[in] data Pointer to buffer with data to send to iic master. + \param[in] size Size of data items to send. + \param[in] timeout Unit of time delay(ms). + \return The amount of real data sent. +*/ +int32_t csi_usi_iic_slave_send(csi_iic_t *iic, const void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start receiving data as iic slave. + This function is blocking. + \param[in] iic Handle to operate. + \param[out] data Pointer to buffer for data to receive from iic master. + \param[in] size Size of data items to receive. + \param[in] timeout Unit of time delay(ms). + \return The amount of real data received. +*/ +int32_t csi_usi_iic_slave_receive(csi_iic_t *iic, void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start sending data as iic slave. + This function is non-blocking,\ref csi_usi_iic_event_t is signaled when transfer completes or error happens. + \param[in] iic Handle to operate. + \param[in] data Pointer to buffer with data to send to iic master. + \param[in] size size of data items to send. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_slave_send_async(csi_iic_t *iic, const void *data, uint32_t size); + +/** + \brief Start receiving data as iic slave. + This function is non-blocking,\ref csi_usi_iic_event_t is signaled when transfer completes or error happens. + \param[in] handle IIC handle to operate. + \param[out] data Pointer to buffer for data to receive from iic master. + \param[in] size Size of data items to receive. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_slave_receive_async(csi_iic_t *iic, void *data, uint32_t size); + +/** + \brief Attach callback to the iic. + \param[in] iic IIC handle to operate. + \param[in] cb Event callback function \ref csi_usi_iic_callback_t. + \param[in] arg User private param for event callback. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_attach_callback(csi_iic_t *iic, void *callback, void *arg); + +/** + \brief Detach callback from the iic. + \param[in] iic IIC handle to operate. + \return \ref csi_error_t. +*/ +void csi_usi_iic_detach_callback(csi_iic_t *iic); + +/** + \brief Config iic stop to generate. + \param[in] iic IIC handle to operate. + \param[in] enable Transfer operation is pending - stop condition will not be generated. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_xfer_pending(csi_iic_t *iic, bool enable); + +/** + \brief Link DMA channel to iic device. + \param[in] iic Handle to operate. + \param[in] tx_dma The DMA channel handle for send, when it is NULL means to unlink the channel. + \param[in] rx_dma The DMA channel handle for receive, when it is NULL means to unlink the channel. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_link_dma(csi_iic_t *iic, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma); + +/** + \brief Get iic state. + \param[in] iic Handle to operate. + \param[out] state IIC state \ref csi_state_t. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_get_state(csi_iic_t *iic, csi_state_t *state); + +/** + \brief Enable iic power manage. + \param[in] iic IIC handle to operate. + \return \ref csi_error_t. +*/ +csi_error_t csi_usi_iic_enable_pm(csi_iic_t *iic); + +/** + \brief Disable iic power manage. + \param[in] iic IIC handle to operate. +*/ +void csi_usi_iic_disable_pm(csi_iic_t *iic); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_USI_IIC_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_spi.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_spi.h new file mode 100644 index 00000000000..eaa1f3e3c88 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_spi.h @@ -0,0 +1,229 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/usi_spi.h + * @brief Header File for SPI Driver + * @version V1.0 + * @date 02. June 2020 + * @model usi_spi + ******************************************************************************/ + +#ifndef _DRV_SPI_USI_H_ +#define _DRV_SPI_USI_H_ + +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + \brief Initialize SPI Interface. + Initializes the resources needed for the SPI instance + \param[in] spi SPI handle + \param[in] idx SPI instance index + \return Error code +*/ +csi_error_t csi_usi_spi_init(csi_spi_t *spi, uint32_t idx); + +/** + \brief De-initialize SPI Interface + Stops operation and releases the software resources used by the spi instance + \param[in] spi SPI handle + \return None +*/ +void csi_usi_spi_uninit(csi_spi_t *spi); + +/** + \brief Attach the callback handler to SPI + \param[in] spi Operate handle. + \param[in] callback Callback function + \param[in] arg User can define it by himself as callback's param + \return Error code +*/ +csi_error_t csi_usi_spi_attach_callback(csi_spi_t *spi, void *callback, void *arg); + +/** + \brief Detach the callback handler + \param[in] spi Operate handle. + \return None +*/ +void csi_usi_spi_detach_callback(csi_spi_t *spi); + + +/** + \brief Config spi mode (master or slave). + \param[in] spi SPI handle + \param[in] mode The mode of spi (master or slave) + \return Error code +*/ +csi_error_t csi_usi_spi_mode(csi_spi_t *spi, csi_spi_mode_t mode); + +/** + \brief Config spi cp format. + \param[in] spi SPI handle + \param[in] format SPI cp format + \return Error code +*/ +csi_error_t csi_usi_spi_cp_format(csi_spi_t *spi, csi_spi_cp_format_t format); + +/** + \brief Config spi frame len. + \param[in] spi SPI handle + \param[in] length spi frame len + \return error code +*/ +csi_error_t csi_usi_spi_frame_len(csi_spi_t *spi, csi_spi_frame_len_t length); + +/** + \brief Config spi work frequence. + \param[in] spi SPI handle + \param[in] baud SPI work baud + \return The actual config frequency +*/ +uint32_t csi_usi_spi_baud(csi_spi_t *spi, uint32_t baud); + +/** + \brief Config spi mode. + \param[in] Handle spi handle to operate. + \param[in] baud SPI baud rate. If negative, then this attribute not changed + \param[in] mode \ref spi_mode_e . If negative, then this attribute not changed + \param[in] format \ref spi_format_e . If negative, then this attribute not changed + \param[in] order \ref spi_bit_order_e . If negative, then this attribute not changed + \param[in] ss_mode \ref spi_ss_mode_t . If negative, then this attribute not changed + \param[in] bit_width SPI data bitwidth: (1 ~ SPI_DATAWIDTH_MAX) . If negative, then this attribute not changed + \return Error code +*/ +csi_error_t drv_usi_spi_config(csi_spi_t *spi, csi_spi_mode_t mode, csi_spi_frame_len_t width, csi_spi_cp_format_t format); + +/** + \brief Sending data to SPI transmitter,(received data is ignored). + Blocking mode ,return unti all data has been sent or err happened + \param[in] spi Handle to operate. + \param[in] data Pointer to buffer with data to send to SPI transmitter. + \param[in] size Number of data to send(byte) + \param[in] timeout Unit in mini-second + \return If send success, this function shall return the num of data witch is sent successful + otherwise, the function shall return error code +*/ +int32_t csi_usi_spi_send(csi_spi_t *spi, const void *data, uint32_t size, uint32_t timeout); + +/** + \brief Sending data to SPI transmitter,(received data is ignored). + non-blocking mode,transfer done event will be signaled by driver + \param[in] spi Handle to operate. + \param[in] data Pointer to buffer with data to send to SPI transmitter. + \param[in] size Number of data items to send(byte) + \return Error code +*/ +csi_error_t csi_usi_spi_send_async(csi_spi_t *spi, const void *data, uint32_t size); + +/** + \brief Receiving data from SPI receiver. + Blocking mode, return untill curtain data items are readed + \param[in] spi Handle to operate. + \param[out] data Pointer to buffer for data to receive from SPI receiver + \param[in] size Number of data items to receive(byte) + \param[in] timeout Unit in mini-second + \return If receive success, this function shall return the num of data witch is received successful + Otherwise, the function shall return error code +*/ +int32_t csi_usi_spi_receive(csi_spi_t *spi, void *data, uint32_t size, uint32_t timeout); + +/** + \brief Receiving data from SPI receiver. + Not-blocking mode, event will be signaled when receive done or err happend + \param[in] spi Handle to operate. + \param[out] data Pointer to buffer for data to receive from SPI receiver + \param[in] size Number of data items to receive(byte) + \return Error code +*/ +csi_error_t csi_usi_spi_receive_async(csi_spi_t *spi, void *data, uint32_t size); + +/** + \brief Dulplex,sending and receiving data at the same time + \ref csi_spi_event_t is signaled when operation completes or error happens. + \ref csi_spi_get_state can get operation status. + Blocking mode, this function returns after operation completes or error happens. + \param[in] Handle spi handle to operate. + \param[in] data_out Pointer to buffer with data to send to SPI transmitter + \param[out] data_in Pointer to buffer for data to receive from SPI receiver + \param[in] size Data size(byte) + \return If transfer success, this function shall return the num of data witch is transfer successful + otherwise, the function shall return error code +*/ +int32_t csi_usi_spi_send_receive(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size, uint32_t timeout); + +/** + \brief Transmit first then receive ,receive will begin after transmit is done + if non-blocking mode, this function only starts the transfer, + \ref csi_spi_event_t is signaled when operation completes or error happens. + \ref csi_spi_get_state can get operation status. + \param[in] handle spi Handle to operate. + \param[in] data_out Pointer to buffer with data to send to SPI transmitter + \param[out] data_in Pointer to buffer for data to receive from SPI receiver + \param[in] size Data size(byte) + \return Error code +*/ +csi_error_t csi_usi_spi_send_receive_async(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size); + +/* + \brief Set slave select num. Only valid for master + \param[in] Handle spi handle to operate. + \param[in] slave_num SPI slave num. + \return None + */ +void csi_usi_spi_select_slave(csi_spi_t *spi, uint32_t slave_num); + +/** + \brief Link DMA channel to spi device + \param[in] spi SPI handle to operate. + \param[in] tx_dma The DMA channel handle for send, when it is NULL means to unlink the channel + \param[in] rx_dma The DMA channel handle for receive, when it is NULL means to unlink the channel + \return Error code +*/ +csi_error_t csi_usi_spi_link_dma(csi_spi_t *spi, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma); + +/** + \brief Get the state of spi device + \param[in] spi SPI handle to operate. + \param[out] state The state of spi device + \return Error code +*/ +csi_error_t csi_usi_spi_get_state(csi_spi_t *spi, csi_state_t *state); + +/** + \brief Enable spi power manage + \param[in] spi SPI handle to operate. + \return Error code +*/ +csi_error_t csi_usi_spi_enable_pm(csi_spi_t *spi); + +/** + \brief Disable spi power manage + \param[in] spi SPI handle to operate. + \return Error code +*/ +void csi_spi_disable_pm(csi_spi_t *spi); +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_SPI_USI_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_usart.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_usart.h new file mode 100644 index 00000000000..59bfe554a52 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/usi_usart.h @@ -0,0 +1,192 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/usi_usart.h + * @brief Header File for USART Driver + * @version V1.0 + * @date 02. June 2020 + * @model usi_usart + ******************************************************************************/ + +#ifndef _DRV_USI_USART_H_ +#define _DRV_USI_USART_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + \brief Initialize UART Interface. 1. Initializes the resources needed for the UART interface 2.registers event callback function + \param[in] uart Operate handle. + \param[in] idx The device idx + \param[in] cb_event Event call back function \ref uart_event_cb_t + \param[in] arg User can define it by himself + \return error code +*/ +csi_error_t csi_usi_uart_init(csi_uart_t *uart, uint32_t idx); + +/** + \brief De-initialize UART Interface. stops operation and releases the software resources used by the interface + \param[in] uart Operate handle. + \return Error code +*/ +void csi_usi_uart_uninit(csi_uart_t *uart); + +/** + \brief Attach the callback handler to UART + \param[in] uart Operate handle. + \param[in] cb Callback function + \param[in] arg User can define it by himself as callback's param + \return Error code +*/ +csi_error_t csi_usi_uart_attach_callback(csi_uart_t *uart, void * cb, void *arg); + +/** + \brief Detach the callback handler + \param[in] uart Operate handle. +*/ +void csi_usi_uart_detach_callback(csi_uart_t *uart); + +/** + \brief Config the baudrate. + \param[in] uart UART handle to operate. + \param[in] baud UART baudrate + \return Error code +*/ +csi_error_t csi_usi_uart_baud(csi_uart_t *uart, uint32_t baud); + +/** + \brief Config the uart format. + \param[in] uart UART handle to operate. + \param[in] data_bit UART data bits + \param[in] parity UART data parity + \param[in] stop_bit UART stop bits + \return Error code +*/ +csi_error_t csi_usi_uart_format(csi_uart_t *uart, csi_uart_data_bits_t data_bits, + csi_uart_parity_t parity, csi_uart_stop_bits_t stop_bits); + +/** + \brief Config the uart flow control. + \param[in] uart UART handle to operate. + \param[in] flowctrl UART flow control + \return Error code +*/ +csi_error_t csi_usi_uart_flowctrl(csi_uart_t *uart, csi_uart_flowctrl_t flowctrl); + +/** + \brief Start sending data to UART transmitter. + \param[in] uart UART handle to operate. + \param[in] data Pointer to buffer with data to send to UART transmitter. data_type is : uint8_t for 5..8 data bits, uint16_t for 9 data bits + \param[in] num Number of data items to send (byte) + \param[in] Timeout is the number of queries, not time + \return The num of data witch is send successful +*/ +int32_t csi_usi_uart_send(csi_uart_t *uart, const void *data, uint32_t size, uint32_t timeout); + +/** + \brief Start sending data to UART transmitter (interrupt mode). + \param[in] uart UART handle to operate. + \param[in] data Pointer to buffer with data to send to UART transmitter. data_type is : uint8_t for 5..8 data bits, uint16_t for 9 data bits + \param[in] num Number of data items to send + \return The status of send func +*/ +csi_error_t csi_usi_uart_send_async(csi_uart_t *uart, const void *data, uint32_t size); + +/** + \brief Get the num of data in RX_FIFO. + \param[in] uart UART handle to operate. + \return The num of data in RX_FIFO +*/ +uint32_t csi_usi_uart_get_recvfifo_waiting_num(csi_uart_t *uart); + +/** + \brief Start receiving data from UART receiver. \n + This function is non-blocking,\ref uart_event_e is signaled when operation completes or error happens. + \ref csi_uart_get_status can get operation status. + \param[in] uart UART handle to operate. + \param[out] data Pointer to buffer for data to receive from UART receiver.data_type is : uint8_t for 5..8 data bits, uint16_t for 9 data bits + \param[in] num Number of data items to receive + \return Error code +*/ +csi_error_t csi_usi_uart_receive_async(csi_uart_t *uart, void *data, uint32_t size); + +/** + \brief Query data from UART receiver FIFO. + \param[in] uart UART handle to operate. + \param[out] data Pointer to buffer for data to receive from UART receiver + \param[in] num Number of data items to receive + \param[in] Timeout is the number of queries, not time + \return FIFO data num to receive +*/ +int32_t csi_usi_uart_receive(csi_uart_t *uart, void *data, uint32_t size, uint32_t timeout); + +/** + \brief Get character in query mode. + \param[in] uart UART handle to operate. + \param[out] ch The pointer to the received character. + \return Error code +*/ +uint8_t csi_usi_uart_getchar(csi_uart_t *uart); + +/** + \brief Transmit character in query mode. + \param[in] uart UART handle to operate. + \param[in] ch The input character + \return Error code +*/ +void csi_usi_uart_putchar(csi_uart_t *uart, uint8_t ch); + +/** + \brief Link DMA channel to uart device + \param[in] uart UART handle to operate. + \param[in] tx_dma The DMA channel handle for send, when it is NULL means to unlink the channel + \param[in] rx_dma The DMA channel handle for receive, when it is NULL means to unlink the channel + \return Error code +*/ +csi_error_t csi_usi_uart_link_dma(csi_uart_t *uart, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma); + +/** + \brief Get the state of uart device. + \param[in] uart UART handle to operate. + \param[out] state The state of uart device. + \return Error code. +*/ +csi_error_t csi_usi_uart_get_state(csi_uart_t *uart, csi_state_t *state); + +/** + \brief Enable uart power manage. + \param[in] uart UART handle to operate. + \return Error code. +*/ +csi_error_t csi_usi_uart_enable_pm(csi_uart_t *uart); + +/** + \brief Disable uart power manage. + \param[in] uart UART handle to operate. +*/ +void csi_usi_uart_disable_pm(csi_uart_t *uart); +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_USI_USART_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/wdt.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/wdt.h new file mode 100644 index 00000000000..d7a824ecaaf --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/drv/wdt.h @@ -0,0 +1,139 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file drv/wdt.h + * @brief Header File for WDT Driver + * @version V1.0 + * @date 9. Oct 2020 + * @model wdt + ******************************************************************************/ + +#ifndef _DRV_WDT_H_ +#define _DRV_WDT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct csi_wdt csi_wdt_t; + +struct csi_wdt { + csi_dev_t dev; + void (*callback)(csi_wdt_t *wdt, void *arg); + void *arg; + void *priv; +}; + +/** + \brief Initialize WDT interface. Initializes the resources needed for the WDT interface + \param[in] wdt Handle to operate + \param[in] idx WDT index + \return Error code \ref csi_error_t +*/ +csi_error_t csi_wdt_init(csi_wdt_t *wdt, uint32_t idx); + +/** + \brief De-initialize WDT interface. Stops operation and releases the software resources used by the interface + \param[in] wdt Handle to operate + \return None +*/ +void csi_wdt_uninit(csi_wdt_t *wdt); + +/** + \brief Set the WDT value + \param[in] wdt Handle to operate + \param[in] ms The timeout value(ms) + \return Error code \ref csi_error_t +*/ +csi_error_t csi_wdt_set_timeout(csi_wdt_t *wdt, uint32_t ms); + +/** + \brief Start the WDT + \param[in] wdt Handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_wdt_start(csi_wdt_t *wdt); + +/** + \brief Stop the WDT + \param[in] wdt Handle to operate + \return None +*/ +void csi_wdt_stop(csi_wdt_t *wdt); + +/** + \brief Feed the WDT + \param[in] wdt Handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_wdt_feed(csi_wdt_t *wdt); + +/** + \brief Get the remaining time to timeout + \param[in] wdt Handle to operate + \return The remaining time of WDT(ms) +*/ +uint32_t csi_wdt_get_remaining_time(csi_wdt_t *wdt); + +/** + \brief Check WDT is running + \param[in] wdt Handle to operate + \return + true - WDT is running + false - WDT is stopped +*/ +bool csi_wdt_is_running(csi_wdt_t *wdt); + +/** + \brief Attach the callback handler to WDT + \param[in] wdt Handle to operate + \param[in] callback Callback function + \param[in] arg Callback's param + \return Error code \ref csi_error_t +*/ +csi_error_t csi_wdt_attach_callback(csi_wdt_t *wdt, void *callback, void *arg); + +/** + \brief Detach the callback handler + \param[in] wdt Handle to operate + \return None +*/ +void csi_wdt_detach_callback(csi_wdt_t *wdt); + +/** + \brief Enable WDT power manage + \param[in] wdt Handle to operate + \return Error code \ref csi_error_t +*/ +csi_error_t csi_wdt_enable_pm(csi_wdt_t *wdt); + +/** + \brief Disable WDT power manage + \param[in] wdt Handle to operate + \return None +*/ +void csi_wdt_disable_pm(csi_wdt_t *wdt); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_WDT_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/syslog.h b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/syslog.h new file mode 100644 index 00000000000..b24586db4f2 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/csi/csi2/include/syslog.h @@ -0,0 +1,121 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file syslog.h + * @brief Defines syslog APIs and usage + * @version V1.1 + * @date 14. February 2019 + * @usage Add 3 lines codes below at head of source code file + * // 0: Err; 1: Err&Warn; 2: Err&Warn&Info; 3: Err&Warn&Info&Debug + * #define LOG_LEVEL 3 + * #include + ******************************************************************************/ +#include + +#ifndef _SYSLOG_H_ +#define _SYSLOG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LOG_LEVEL +#if (LOG_LEVEL >= 3) && \ + (defined CONFIG_SYSLOG_LEVEL_DEBUG) +#define LOG_ENABLE_D +#endif + +#if (LOG_LEVEL >= 2) && \ + (defined CONFIG_SYSLOG_LEVEL_DEBUG || \ + defined CONFIG_SYSLOG_LEVEL_INFO) +#define LOG_ENABLE_I +#endif + +#if (LOG_LEVEL >= 1) && \ + (defined CONFIG_SYSLOG_LEVEL_DEBUG || \ + defined CONFIG_SYSLOG_LEVEL_INFO || \ + defined CONFIG_SYSLOG_LEVEL_WARN) +#define LOG_ENABLE_W +#endif + +#if (LOG_LEVEL >= 0) && \ + (defined CONFIG_SYSLOG_LEVEL_DEBUG || \ + defined CONFIG_SYSLOG_LEVEL_INFO || \ + defined CONFIG_SYSLOG_LEVEL_WARN || \ + defined CONFIG_SYSLOG_LEVEL_ERROR) +#define LOG_ENABLE_E +#endif +#endif /* #ifdef LOG_LEVEL */ + +/* [LogLevel:FileName:Function:Line] */ +extern const char *PFORMAT_D; +extern const char *PFORMAT_I; +extern const char *PFORMAT_W; +extern const char *PFORMAT_E; + +#define LOG_E_BASE_ARGS __FUNCTION__, __LINE__ +#define LOG_W_BASE_ARGS __FUNCTION__, __LINE__ +#define LOG_I_BASE_ARGS __FUNCTION__, __LINE__ +#define LOG_D_BASE_ARGS __FUNCTION__, __LINE__ + +/* Log in freely format without prefix */ +#define LOG_F(fmt, args...) printf(fmt,##args) + +/* Log debug */ +#ifdef LOG_ENABLE_D +#define LOG_D(fmt, args...) \ + do {printf(PFORMAT_D,LOG_D_BASE_ARGS); printf(fmt,##args);} while(0) +#else +#define LOG_D(fmt, args...) +#endif + +/* Log information */ +#ifdef LOG_ENABLE_I +#define LOG_I(fmt, args...) \ + do {printf(PFORMAT_I ,LOG_I_BASE_ARGS); printf(fmt,##args);} while(0) +#else +#define LOG_I(fmt, args...) +#endif + +/* Log warning */ +#ifdef LOG_ENABLE_W +#define LOG_W(fmt, args...) \ + do {printf(PFORMAT_W,LOG_W_BASE_ARGS); printf(fmt,##args);} while(0) +#else +#define LOG_W(fmt, args...) +#endif + +/* Log error */ +#ifdef LOG_ENABLE_E +#define LOG_E(fmt, args...) \ + do {printf(PFORMAT_E,LOG_E_BASE_ARGS); printf(fmt,##args);} while(0) +#else +#define LOG_E(fmt, args...) +#endif + +#define ENTER() LOG_D("Enter\n") +#define EXIT_VOID() do { LOG_D("Exit\n"); return;} while(0) +#define EXIT_INT(val) do { LOG_D("Exit, return val=%d\n", (int)val); return val;} while(0) +#define EXIT_PTR(ptr) do { LOG_D("Exit, return ptr=%p\n", (void*)ptr); return ptr;} while(0) + +#ifdef __cplusplus +} +#endif + +#endif /* _SYSLOG_H_ */ diff --git a/bsp/xuantie/libraries/xuantie_libraries/pre_main/SConscript b/bsp/xuantie/libraries/xuantie_libraries/pre_main/SConscript new file mode 100644 index 00000000000..f530983e5c4 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/pre_main/SConscript @@ -0,0 +1,11 @@ +from building import * +import os + +cwd = GetCurrentDir() +CPPPATH = [cwd] +src = ['pre_main.c'] +src += ['sub_libcpu.S'] + +group = DefineGroup('pre_main', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/xuantie/libraries/xuantie_libraries/pre_main/pre_main.c b/bsp/xuantie/libraries/xuantie_libraries/pre_main/pre_main.c new file mode 100644 index 00000000000..d098ca20c08 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/pre_main/pre_main.c @@ -0,0 +1,82 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/****************************************************************************** + * @file pre_main.c + * @brief source file for the pre_main + * @version V1.0 + * @date 04. April 2024 + ******************************************************************************/ +#include "pre_main.h" + +/* + * The ranges of copy from/to are specified by following symbols + * __erodata: LMA of start of the section to copy from. Usually end of rodata + * __data_start__: VMA of start of the section to copy to + * __data_end__: VMA of end of the section to copy to + * + * All addresses must be aligned to 4 bytes boundary. + */ +void section_data_copy(void) +{ + extern unsigned long __erodata; + extern unsigned long __data_start__; + extern unsigned long __data_end__; + + if (((unsigned long)&__erodata != (unsigned long)&__data_start__)) { + unsigned long src_addr = (unsigned long)&__erodata; + memcpy((void *)(&__data_start__), \ + (void *)src_addr, \ + (unsigned long)(&__data_end__) - (unsigned long)(&__data_start__)); + } +} + +void section_ram_code_copy(void) +{ + extern unsigned long __erodata; + extern unsigned long __data_start__; + extern unsigned long __data_end__; + extern unsigned long __ram_code_start__; + extern unsigned long __ram_code_end__; + + if (((unsigned long)&__erodata != (unsigned long)&__data_start__)) { + unsigned long src_addr = (unsigned long)&__erodata; + src_addr += (unsigned long)(&__data_end__) - (unsigned long)(&__data_start__); + memcpy((void *)(&__ram_code_start__), \ + (void *)src_addr, \ + (unsigned long)(&__ram_code_end__) - (unsigned long)(&__ram_code_start__)); + } +} + +/* + * The BSS section is specified by following symbols + * __bss_start__: start of the BSS section. + * __bss_end__: end of the BSS section. + * + * Both addresses must be aligned to 4 bytes boundary. + */ +void section_bss_clear(void) +{ + extern unsigned long __bss_start__; + extern unsigned long __bss_end__; + + memset((void *)(&__bss_start__), \ + 0, \ + (unsigned long)(&__bss_end__) - (unsigned long)(&__bss_start__)); + +} diff --git a/bsp/xuantie/libraries/xuantie_libraries/pre_main/pre_main.h b/bsp/xuantie/libraries/xuantie_libraries/pre_main/pre_main.h new file mode 100644 index 00000000000..c100d13d6d3 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/pre_main/pre_main.h @@ -0,0 +1,12 @@ +#ifndef PRE_MAIN_H_ +#define PRE_MAIN_H_ + +#include +#include + +void section_data_copy(void); +void section_ram_code_copy(void); +void section_ram_code_copy(void); +void section_bss_clear(void); + +#endif // PRE_MAIN_H_ diff --git a/bsp/xuantie/libraries/xuantie_libraries/pre_main/sub_libcpu.S b/bsp/xuantie/libraries/xuantie_libraries/pre_main/sub_libcpu.S new file mode 100644 index 00000000000..184ba0c71f6 --- /dev/null +++ b/bsp/xuantie/libraries/xuantie_libraries/pre_main/sub_libcpu.S @@ -0,0 +1,15 @@ +#include "cpuport.h" + +.globl rt_hw_do_after_save_above +.type rt_hw_do_after_save_above,@function +rt_hw_do_after_save_above: +addi sp, sp, -4 + STORE ra, 0 * REGBYTES(sp) + + csrr a0, mscratch + call do_irq + + LOAD ra, 0 * REGBYTES(sp) + addi sp, sp, 4 + ret + \ No newline at end of file diff --git a/bsp/xuantie/smartl/e906/.config b/bsp/xuantie/smartl/e906/.config new file mode 100644 index 00000000000..01cd40e7d54 --- /dev/null +++ b/bsp/xuantie/smartl/e906/.config @@ -0,0 +1,1355 @@ +CONFIG_XUANTIAN_XIAOHUI_E906=y + +# +# RT-Thread Kernel +# + +# +# klibc options +# + +# +# rt_vsnprintf options +# +# CONFIG_RT_KLIBC_USING_LIBC_VSNPRINTF is not set +# CONFIG_RT_KLIBC_USING_VSNPRINTF_LONGLONG is not set +# CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD is not set +# end of rt_vsnprintf options + +# +# rt_vsscanf options +# +# CONFIG_RT_KLIBC_USING_LIBC_VSSCANF is not set +# end of rt_vsscanf options + +# +# rt_memset options +# +# CONFIG_RT_KLIBC_USING_USER_MEMSET is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMSET is not set +# CONFIG_RT_KLIBC_USING_TINY_MEMSET is not set +# end of rt_memset options + +# +# rt_memcpy options +# +# CONFIG_RT_KLIBC_USING_USER_MEMCPY is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMCPY is not set +# CONFIG_RT_KLIBC_USING_TINY_MEMCPY is not set +# end of rt_memcpy options + +# +# rt_memmove options +# +# CONFIG_RT_KLIBC_USING_USER_MEMMOVE is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMMOVE is not set +# end of rt_memmove options + +# +# rt_memcmp options +# +# CONFIG_RT_KLIBC_USING_USER_MEMCMP is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMCMP is not set +# end of rt_memcmp options + +# +# rt_strstr options +# +# CONFIG_RT_KLIBC_USING_USER_STRSTR is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRSTR is not set +# end of rt_strstr options + +# +# rt_strcasecmp options +# +# CONFIG_RT_KLIBC_USING_USER_STRCASECMP is not set +# end of rt_strcasecmp options + +# +# rt_strncpy options +# +# CONFIG_RT_KLIBC_USING_USER_STRNCPY is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRNCPY is not set +# end of rt_strncpy options + +# +# rt_strcpy options +# +# CONFIG_RT_KLIBC_USING_USER_STRCPY is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRCPY is not set +# end of rt_strcpy options + +# +# rt_strncmp options +# +# CONFIG_RT_KLIBC_USING_USER_STRNCMP is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRNCMP is not set +# end of rt_strncmp options + +# +# rt_strcmp options +# +# CONFIG_RT_KLIBC_USING_USER_STRCMP is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRCMP is not set +# end of rt_strcmp options + +# +# rt_strlen options +# +# CONFIG_RT_KLIBC_USING_USER_STRLEN is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRLEN is not set +# end of rt_strlen options + +# +# rt_strnlen options +# +# CONFIG_RT_KLIBC_USING_USER_STRNLEN is not set +# end of rt_strnlen options + +# CONFIG_RT_UTEST_TC_USING_KLIBC is not set +# end of klibc options + +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_NANO is not set +# CONFIG_RT_USING_AMP is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_CPUS_NR=1 +CONFIG_RT_ALIGN_SIZE=8 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=1000 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_HOOK_USING_FUNC_PTR=y +# CONFIG_RT_USING_HOOKLIST is not set +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=1024 +CONFIG_RT_USING_TIMER_SOFT=y +CONFIG_RT_TIMER_THREAD_PRIO=4 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=1024 +# CONFIG_RT_USING_TIMER_ALL_SOFT is not set +# CONFIG_RT_USING_CPU_USAGE_TRACER is not set + +# +# kservice options +# +# CONFIG_RT_USING_TINY_FFS is not set +# end of kservice options + +CONFIG_RT_USING_DEBUG=y +CONFIG_RT_DEBUGING_ASSERT=y +CONFIG_RT_DEBUGING_COLOR=y +CONFIG_RT_DEBUGING_CONTEXT=y +# CONFIG_RT_DEBUGING_AUTO_INIT is not set +# CONFIG_RT_USING_CI_ACTION is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_MESSAGEQUEUE_PRIORITY is not set +# CONFIG_RT_USING_SIGNALS is not set +# end of Inter-Thread communication + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMHEAP is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +# CONFIG_RT_USING_HEAP_ISR is not set +CONFIG_RT_USING_HEAP=y +# end of Memory Management + +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +# CONFIG_RT_USING_THREADSAFE_PRINTF is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" +CONFIG_RT_VER_NUM=0x50201 +# CONFIG_RT_USING_STDC_ATOMIC is not set +CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32 +# end of RT-Thread Kernel + +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_RISCV_FPU=y +# CONFIG_ARCH_RISCV_FPU_S is not set +CONFIG_ARCH_RISCV_FPU_D=y +CONFIG_ARCH_RISCV32=y + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set +CONFIG_RT_USING_MSH=y +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 +CONFIG_FINSH_USING_OPTION_COMPLETION=y + +# +# DFS: device virtual file system +# +# CONFIG_RT_USING_DFS is not set +# end of DFS: device virtual file system + +# CONFIG_RT_USING_FAL is not set + +# +# Device Drivers +# +# CONFIG_RT_USING_DM is not set +# CONFIG_RT_USING_DEV_BUS is not set +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_UNAMED_PIPE_NUMBER=64 +# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +# CONFIG_RT_SERIAL_USING_DMA is not set +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_SERIAL_BYPASS is not set +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +# CONFIG_RT_USING_PHY_V2 is not set +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_NULL is not set +# CONFIG_RT_USING_ZERO is not set +# CONFIG_RT_USING_RANDOM is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_LCD is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_WIFI is not set +# CONFIG_RT_USING_BLK is not set +# CONFIG_RT_USING_VIRTIO is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_KTIME is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CHERRYUSB is not set +# end of Device Drivers + +# +# C/C++ and POSIX layer +# + +# +# ISO-ANSI C layer +# + +# +# Timezone and Daylight Saving Time +# +# CONFIG_RT_LIBC_USING_FULL_TZ_DST is not set +CONFIG_RT_LIBC_USING_LIGHT_TZ_DST=y +CONFIG_RT_LIBC_TZ_DEFAULT_HOUR=8 +CONFIG_RT_LIBC_TZ_DEFAULT_MIN=0 +CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 +# end of Timezone and Daylight Saving Time +# end of ISO-ANSI C layer + +# +# POSIX (Portable Operating System Interface) layer +# +# CONFIG_RT_USING_POSIX_FS is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_POSIX_TIMER is not set +# CONFIG_RT_USING_PTHREADS is not set +# CONFIG_RT_USING_MODULE is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# +# end of Interprocess Communication (IPC) +# end of POSIX (Portable Operating System Interface) layer + +# CONFIG_RT_USING_CPLUSPLUS is not set +# end of C/C++ and POSIX layer + +# +# Network +# +# CONFIG_RT_USING_SAL is not set +# CONFIG_RT_USING_NETDEV is not set +# CONFIG_RT_USING_LWIP is not set +# CONFIG_RT_USING_AT is not set +# end of Network + +# +# Memory protection +# +# CONFIG_RT_USING_MEM_PROTECTION is not set +# CONFIG_RT_USING_HW_STACK_GUARD is not set +# end of Memory protection + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RESOURCE_ID is not set +# CONFIG_RT_USING_ADT is not set +# CONFIG_RT_USING_RT_LINK is not set +# end of Utilities + +# CONFIG_RT_USING_VBUS is not set + +# +# Using USB legacy version +# +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set +# end of Using USB legacy version + +# CONFIG_RT_USING_FDT is not set +# end of RT-Thread Components + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set +# end of RT-Thread Utestcases + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_NANOPB is not set +# CONFIG_PKG_USING_WIFI_HOST_DRIVER is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set +# end of Marvell WiFi + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# end of Wiced WiFi + +# CONFIG_PKG_USING_RW007 is not set + +# +# CYW43012 WiFi +# +# CONFIG_PKG_USING_WLAN_CYW43012 is not set +# end of CYW43012 WiFi + +# +# BL808 WiFi +# +# CONFIG_PKG_USING_WLAN_BL808 is not set +# end of BL808 WiFi + +# +# CYW43439 WiFi +# +# CONFIG_PKG_USING_WLAN_CYW43439 is not set +# end of CYW43439 WiFi +# end of Wi-Fi + +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_IOTSHARP_SDK is not set +# end of IoT Cloud + +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_BT_CYW43012 is not set +# CONFIG_PKG_USING_CYW43XX is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_RYANMQTT is not set +# CONFIG_PKG_USING_RYANW5500 is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set +# CONFIG_PKG_USING_ZFTP is not set +# CONFIG_PKG_USING_WOL is not set +# CONFIG_PKG_USING_ZEPHYR_POLLING is not set +# CONFIG_PKG_USING_MATTER_ADAPTATION_LAYER is not set +# CONFIG_PKG_USING_LHC_MODBUS is not set +# CONFIG_PKG_USING_QMODBUS is not set +# CONFIG_PKG_USING_PNET is not set +# CONFIG_PKG_USING_OPENER is not set +# end of IoT - internet of things + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_LIBSODIUM is not set +# CONFIG_PKG_USING_LIBHYDROGEN is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set +# end of security packages + +# +# language packages +# + +# +# JSON: JavaScript Object Notation, a lightweight data-interchange format +# +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PARSON is not set +# CONFIG_PKG_USING_RYAN_JSON is not set +# end of JSON: JavaScript Object Notation, a lightweight data-interchange format + +# +# XML: Extensible Markup Language +# +# CONFIG_PKG_USING_SIMPLE_XML is not set +# CONFIG_PKG_USING_EZXML is not set +# end of XML: Extensible Markup Language + +# CONFIG_PKG_USING_LUATOS_SOC is not set +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set +# CONFIG_PKG_USING_RTT_RUST is not set +# end of language packages + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set +# CONFIG_PKG_USING_GUI_GUIDER_DEMO is not set +# end of LVGL: powerful and easy-to-use embedded GUI library + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# end of u8g2: a monochrome graphic library + +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_3GPP_AMRNB is not set +# end of multimedia packages + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RTT_AUTO_EXE_CMD is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set +# CONFIG_PKG_USING_CBOX is not set +# CONFIG_PKG_USING_SNOWFLAKE is not set +# CONFIG_PKG_USING_HASH_MATCH is not set +# CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set +# CONFIG_PKG_USING_VOFA_PLUS is not set +# CONFIG_PKG_USING_ZDEBUG is not set +# CONFIG_PKG_USING_RVBACKTRACE is not set +# CONFIG_PKG_USING_HPATCHLITE is not set +# end of tools packages + +# +# system packages +# + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# end of enhanced kernel services + +# CONFIG_PKG_USING_AUNITY is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set +# end of acceleration: Assembly language or algorithmic acceleration packages + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_CORE is not set +# CONFIG_PKG_USING_CMSIS_NN is not set +# CONFIG_PKG_USING_CMSIS_RTOS1 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set +# end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# end of Micrium: Micrium software products porting for RT-Thread + +# CONFIG_PKG_USING_FREERTOS_WRAPPER is not set +# CONFIG_PKG_USING_LITEOS_SDK is not set +# CONFIG_PKG_USING_TZ_DATABASE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_PERF_COUNTER is not set +# CONFIG_PKG_USING_FILEX is not set +# CONFIG_PKG_USING_LEVELX is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RPMSG_LITE is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_KMULTI_RTIMER is not set +# CONFIG_PKG_USING_TFDB is not set +# CONFIG_PKG_USING_QPC is not set +# CONFIG_PKG_USING_AGILE_UPGRADE is not set +# CONFIG_PKG_USING_FLASH_BLOB is not set +# CONFIG_PKG_USING_MLIBC is not set +# CONFIG_PKG_USING_TASK_MSG_BUS is not set +# CONFIG_PKG_USING_UART_FRAMEWORK is not set +# CONFIG_PKG_USING_SFDB is not set +# CONFIG_PKG_USING_RTP is not set +# CONFIG_PKG_USING_REB is not set +# CONFIG_PKG_USING_RMP is not set +# CONFIG_PKG_USING_R_RHEALSTONE is not set +# CONFIG_PKG_USING_HEARTBEAT is not set +# end of system packages + +# +# peripheral libraries and drivers +# + +# +# HAL & SDK Drivers +# + +# +# STM32 HAL & SDK Drivers +# +# CONFIG_PKG_USING_STM32F0_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32F0_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32F1_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32F1_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32F2_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32F2_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32F3_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32F3_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32F4_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32F4_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32F7_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32F7_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32G0_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32G0_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32G4_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32G4_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32H5_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32H5_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32H7_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32H7_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32H7RS_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32H7RS_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32L0_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32L0_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32L4_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32L4_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32L5_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32L5_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32U5_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32U5_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_STM32WL_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32WL_CMSIS_DRIVER is not set +# end of STM32 HAL & SDK Drivers + +# +# Infineon HAL Packages +# +# CONFIG_PKG_USING_INFINEON_CAT1CM0P is not set +# CONFIG_PKG_USING_INFINEON_CMSIS is not set +# CONFIG_PKG_USING_INFINEON_CORE_LIB is not set +# CONFIG_PKG_USING_INFINEON_MTB_HAL_CAT1 is not set +# CONFIG_PKG_USING_INFINEON_MTB_PDL_CAT1 is not set +# CONFIG_PKG_USING_INFINEON_RETARGET_IO is not set +# CONFIG_PKG_USING_INFINEON_CAPSENSE is not set +# CONFIG_PKG_USING_INFINEON_CSDIDAC is not set +# CONFIG_PKG_USING_INFINEON_SERIAL_FLASH is not set +# CONFIG_PKG_USING_INFINEON_USBDEV is not set +# end of Infineon HAL Packages + +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_ESP_IDF is not set + +# +# Kendryte SDK +# +# CONFIG_PKG_USING_K210_SDK is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# end of Kendryte SDK + +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_NUCLEI_SDK is not set +# CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set +# CONFIG_PKG_USING_MM32 is not set + +# +# WCH HAL & SDK Drivers +# +# CONFIG_PKG_USING_CH32V20x_SDK is not set +# CONFIG_PKG_USING_CH32V307_SDK is not set +# end of WCH HAL & SDK Drivers + +# +# AT32 HAL & SDK Drivers +# +# CONFIG_PKG_USING_AT32A403A_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32A403A_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32A423_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32A423_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F45x_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F45x_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F402_405_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F402_405_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F403A_407_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F403A_407_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F413_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F413_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F415_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F415_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F421_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F421_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F423_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F423_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F425_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F425_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F435_437_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F435_437_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32M412_416_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32M412_416_CMSIS_DRIVER is not set +# end of AT32 HAL & SDK Drivers +# end of HAL & SDK Drivers + +# +# sensors drivers +# +# CONFIG_PKG_USING_LSM6DSM is not set +# CONFIG_PKG_USING_LSM6DSL is not set +# CONFIG_PKG_USING_LPS22HB is not set +# CONFIG_PKG_USING_HTS221 is not set +# CONFIG_PKG_USING_LSM303AGR is not set +# CONFIG_PKG_USING_BME280 is not set +# CONFIG_PKG_USING_BME680 is not set +# CONFIG_PKG_USING_BMA400 is not set +# CONFIG_PKG_USING_BMI160_BMX160 is not set +# CONFIG_PKG_USING_SPL0601 is not set +# CONFIG_PKG_USING_MS5805 is not set +# CONFIG_PKG_USING_DA270 is not set +# CONFIG_PKG_USING_DF220 is not set +# CONFIG_PKG_USING_HSHCAL001 is not set +# CONFIG_PKG_USING_BH1750 is not set +# CONFIG_PKG_USING_MPU6XXX is not set +# CONFIG_PKG_USING_AHT10 is not set +# CONFIG_PKG_USING_AP3216C is not set +# CONFIG_PKG_USING_TSL4531 is not set +# CONFIG_PKG_USING_DS18B20 is not set +# CONFIG_PKG_USING_DHT11 is not set +# CONFIG_PKG_USING_DHTXX is not set +# CONFIG_PKG_USING_GY271 is not set +# CONFIG_PKG_USING_GP2Y10 is not set +# CONFIG_PKG_USING_SGP30 is not set +# CONFIG_PKG_USING_HDC1000 is not set +# CONFIG_PKG_USING_BMP180 is not set +# CONFIG_PKG_USING_BMP280 is not set +# CONFIG_PKG_USING_SHTC1 is not set +# CONFIG_PKG_USING_BMI088 is not set +# CONFIG_PKG_USING_HMC5883 is not set +# CONFIG_PKG_USING_MAX6675 is not set +# CONFIG_PKG_USING_MAX31855 is not set +# CONFIG_PKG_USING_TMP1075 is not set +# CONFIG_PKG_USING_SR04 is not set +# CONFIG_PKG_USING_CCS811 is not set +# CONFIG_PKG_USING_PMSXX is not set +# CONFIG_PKG_USING_RT3020 is not set +# CONFIG_PKG_USING_MLX90632 is not set +# CONFIG_PKG_USING_MLX90382 is not set +# CONFIG_PKG_USING_MLX90393 is not set +# CONFIG_PKG_USING_MLX90392 is not set +# CONFIG_PKG_USING_MLX90394 is not set +# CONFIG_PKG_USING_MLX90397 is not set +# CONFIG_PKG_USING_MS5611 is not set +# CONFIG_PKG_USING_MAX31865 is not set +# CONFIG_PKG_USING_VL53L0X is not set +# CONFIG_PKG_USING_INA260 is not set +# CONFIG_PKG_USING_MAX30102 is not set +# CONFIG_PKG_USING_INA226 is not set +# CONFIG_PKG_USING_LIS2DH12 is not set +# CONFIG_PKG_USING_HS300X is not set +# CONFIG_PKG_USING_ZMOD4410 is not set +# CONFIG_PKG_USING_ISL29035 is not set +# CONFIG_PKG_USING_MMC3680KJ is not set +# CONFIG_PKG_USING_QMP6989 is not set +# CONFIG_PKG_USING_BALANCE is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_SHT4X is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_ADT74XX is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_CW2015 is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_STHS34PF80 is not set +# CONFIG_PKG_USING_P3T1755 is not set +# end of sensors drivers + +# +# touch drivers +# +# CONFIG_PKG_USING_GT9147 is not set +# CONFIG_PKG_USING_GT1151 is not set +# CONFIG_PKG_USING_GT917S is not set +# CONFIG_PKG_USING_GT911 is not set +# CONFIG_PKG_USING_FT6206 is not set +# CONFIG_PKG_USING_FT5426 is not set +# CONFIG_PKG_USING_FT6236 is not set +# CONFIG_PKG_USING_XPT2046_TOUCH is not set +# CONFIG_PKG_USING_CST816X is not set +# CONFIG_PKG_USING_CST812T is not set +# end of touch drivers + +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_MULTI_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_ILI9341 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set +# CONFIG_PKG_USING_RFM300 is not set +# CONFIG_PKG_USING_IO_INPUT_FILTER is not set +# CONFIG_PKG_USING_LRF_NV7LIDAR is not set +# CONFIG_PKG_USING_AIP650 is not set +# CONFIG_PKG_USING_FINGERPRINT is not set +# CONFIG_PKG_USING_BT_ECB02C is not set +# CONFIG_PKG_USING_UAT is not set +# CONFIG_PKG_USING_ST7789 is not set +# CONFIG_PKG_USING_VS1003 is not set +# CONFIG_PKG_USING_X9555 is not set +# CONFIG_PKG_USING_SYSTEM_RUN_LED is not set +# CONFIG_PKG_USING_BT_MX01 is not set +# CONFIG_PKG_USING_RGPOWER is not set +# CONFIG_PKG_USING_BT_MX02 is not set +# CONFIG_PKG_USING_GC9A01 is not set +# CONFIG_PKG_USING_IK485 is not set +# CONFIG_PKG_USING_SERVO is not set +# CONFIG_PKG_USING_SPI_TOOLS is not set +# end of peripheral libraries and drivers + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set +# CONFIG_PKG_USING_R_TINYMAIX is not set +# CONFIG_PKG_USING_LLMCHAT is not set +# end of AI packages + +# +# Signal Processing and Control Algorithm Packages +# +# CONFIG_PKG_USING_APID is not set +# CONFIG_PKG_USING_FIRE_PID_CURVE is not set +# CONFIG_PKG_USING_QPID is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_KISSFFT is not set +# end of Signal Processing and Control Algorithm Packages + +# +# miscellaneous packages +# + +# +# project laboratory +# +# end of project laboratory + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set +# end of samples: kernel and components samples + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_MORSE is not set +# end of entertainment: terminal games and other interesting software packages + +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_RALARAM is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_HEATSHRINK is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LIBCRC is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set +# CONFIG_PKG_USING_MFBD is not set +# CONFIG_PKG_USING_SLCAN2RTT is not set +# CONFIG_PKG_USING_SOEM is not set +# CONFIG_PKG_USING_QPARAM is not set +# CONFIG_PKG_USING_CorevMCU_CLI is not set +# CONFIG_PKG_USING_DRMP is not set +# end of miscellaneous packages + +# +# Arduino libraries +# +# CONFIG_PKG_USING_RTDUINO is not set + +# +# Projects and Demos +# +# CONFIG_PKG_USING_ARDUINO_MSGQ_C_CPP_DEMO is not set +# CONFIG_PKG_USING_ARDUINO_SKETCH_LOADER_DEMO is not set +# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set +# CONFIG_PKG_USING_ARDUINO_RTDUINO_SENSORFUSION_SHIELD is not set +# CONFIG_PKG_USING_ARDUINO_NINEINONE_SENSOR_SHIELD is not set +# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set +# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set +# end of Projects and Demos + +# +# Sensors +# +# CONFIG_PKG_USING_ARDUINO_SENSOR_DEVICE_DRIVERS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSORLAB is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L1X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL6180X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31855 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX6675 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MSA301 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL335 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_H3LIS331DL is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MMA7660 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PAJ7620 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VL53L0X is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ITG3200 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HP20X is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DRV2605L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BBM150 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HMC5883L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM303DLH is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TCS3414CS is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MP503 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HIGHTEMP is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT35 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_AT42QT1070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM6DS3 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HM3301 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LTC2941 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LDC1612 is not set +# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set +# CONFIG_PKG_USING_ARDUINO_JARZEBSKI_MPU6050 is not set +# end of Sensors + +# +# Display +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_GFX_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_U8G2 is not set +# CONFIG_PKG_USING_ARDUINO_TFT_ESPI is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ST7735 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SSD1306 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ILI9341 is not set +# CONFIG_PKG_USING_SEEED_TM1637 is not set +# end of Display + +# +# Timing +# +# CONFIG_PKG_USING_ARDUINO_RTCLIB is not set +# CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set +# CONFIG_PKG_USING_ARDUINO_TICKER is not set +# CONFIG_PKG_USING_ARDUINO_TASKSCHEDULER is not set +# end of Timing + +# +# Data Processing +# +# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set +# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set +# CONFIG_PKG_USING_ARDUINO_TENSORFLOW_LITE_MICRO is not set +# CONFIG_PKG_USING_ARDUINO_RUNNINGMEDIAN is not set +# end of Data Processing + +# +# Data Storage +# + +# +# Communication +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set +# end of Communication + +# +# Device Control +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TPA2016 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DRV2605 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DS1841 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DS3502 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set +# end of Device Control + +# +# Other +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MFRC630 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI5351 is not set +# end of Other + +# +# Signal IO +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set +# end of Signal IO + +# +# Uncategorized +# +# end of Arduino libraries +# end of RT-Thread online packages + +# +# Hardware Drivers Config +# +CONFIG_SOC_XUANTIE=y + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART0=y +CONFIG_ENABLE_FPU=y +# end of On-chip Peripheral Drivers +# end of Hardware Drivers Config diff --git a/bsp/xuantie/smartl/e906/Kconfig b/bsp/xuantie/smartl/e906/Kconfig new file mode 100644 index 00000000000..1c1250199f0 --- /dev/null +++ b/bsp/xuantie/smartl/e906/Kconfig @@ -0,0 +1,18 @@ +mainmenu "RT-Thread Configuration" + +BSP_DIR := . + +RTT_DIR := ../../../.. + +PKGS_DIR := packages + +config XUANTIAN_XIAOHUI_E906 + bool + select ARCH_RISCV32 + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +source "$(RTT_DIR)/Kconfig" +osource "$PKGS_DIR/Kconfig" +rsource "board/Kconfig" diff --git a/bsp/xuantie/smartl/e906/README.md b/bsp/xuantie/smartl/e906/README.md new file mode 100644 index 00000000000..f67355f92df --- /dev/null +++ b/bsp/xuantie/smartl/e906/README.md @@ -0,0 +1,107 @@ +# XuanTie - E906 Series + +## 一 简介 + +### 1. 内核 + +[E906](https://www.xrvm.cn/community/download?id=4222755171580579840) 是一款基于 RISC-V 指令集的高能效嵌入式处理器,是玄铁 RISC-V MCU 产品线中的最高性能 +处理器。 E906 的设计目标是,使用最低的面积和功耗成本,取得相对较高的性能指标。 E906 主要面向语 +音、高端 MCU、轻量级 AI、导航、 WiFi 等应用领域。 + +### 2.特点 + +E906 处理器体系结构的主要特点如下: +• 32 位 RISC 处理器; +• 支持 RISC-V RV32IMA[F][D]C[P] 指令集; +• 支持 RISC-V 32/16 位混编指令集; +• 32 个 32 位通用寄存器; +• 整型 5 级/浮点 7 级,单发射,顺序执行流水线; +• 可选配 BHT 和 BTB; +• 支持 RISC-V 机器模式和用户模式; +• 双周期硬件乘法器,基 4 硬件除法器; +• 可选配指令 cache,两路组相连结构, 2KiB-32KiB 可配置; +• 可选配数据 cache,两路组相连结构, 2KiB-32KiB 可配置; +• 兼容 RISC-V CLIC 中断标准,支持中断嵌套,外部中断源数量最高可配置 240 个; +• 兼容 RISC-V PMP 内存保护标准, 0/4/8/12/16 区域可配置; +• 支持 AHB-Lite 总线协议,支持三条总线:指令总线,数据总线和系统总线; +• 支持可配的性能监测单元; +• 支持玄铁扩展增强指令集 + +### 3.BSP支持情况 + +- 当前BSP支持下述内核: + + ```asciiarmor + e906 e906f e906fd e906p e906fp e906fdp + ``` + +- 当前BSP默认设置的内核是e906fd,该架构支持[F] [D]扩展,可以通过menuconfig工具使能[F]扩展或者[F] [D] 扩展。 + +- 当使用其他内核架构时需要修改,rtconfig.py文件中的`MCPU`与`CPU`字段。 + +## 二 工具 + +- 编译器: https://www.xrvm.cn/community/download?id=4433353576298909696 +- 模拟器: https://www.xrvm.cn/community/download?id=4397435198627713024 + +注:若上述链接中的编译器与模拟器不能使用,可以使用下述CDK中的编译器与模拟器 + +- SDK:https://www.xrvm.cn/community/download?id=4397799570420076544 + +## 三 编译运行 + +在BSP根目录打开env工具。 + +![](figures/1.env.png) + +首次使用执行一次**menuconfig**命令,更新**rtconfig.h**配置,然后在当前目录执行**scons -j12**编译生成**rtthread.elf**可执行文件。 + +![](figures/2.scons.png) + +BSP根目录下存在`qemu.bat`脚本,生成可执行文件后可点击该脚本直接启动QEMU. + +在Windows环境下双击运行该脚本,出现下述页面,首次运行需要输入QEMU可执行文件的路径,后续如果不修改QEMU的路径,直接按回车跳过当前步骤: + +![](figures/4.run1.png) + +第二步需要设置`-cpu`的参数,当前脚默认为`e906fd`,如果需要修改请在`:`后输入具体内核型号,例如`e906` + +![](figures/5.run2.png) + +完成参数设置后按回车键便可以在qemu上运行可执行文件。 + +注:当前BSP根目录存在`objdump.bat`脚本文件,点击该脚本可以在BSP根目录生成反汇编文件。 + +## 四 调试方法 + +### 1. 命令行调试 + +当前BSP可以在命令行启动qemu或者配置vscode脚本借助vscode强大的插件进行图形化调试,qemu的相关命令可以查看玄铁qemu的[用户手册](https://www.xrvm.cn/community/download?id=4397435198627713024),下述是启动qemu的命令,在powershell或命令行可直接执行下述命令,**注意QEMU需要导出至环境变量或者使用绝对路径**。 + +```shell +qemu-system-riscv32 -machine smartl -nographic -kernel rtthread.elf -cpu e906fd -gdb tcp::23333 -S +``` + +启动`powershell`或命令行,输入并执行上述命令后的视图。 + +![](figures/6.cmd1.png) + +启动另一个`powershell`或命令行,输入并执行下述命令后的视图如下,**注意GDB需要导出至环境变量或者使用绝对路径**。。 + +```shell +riscv64-unknown-elf-gdb.exe rtthread.elf -ex "target remote localhost:23333" +``` + +![](figures/7.cmd2.png) + +如果不设置断点,在命令行执行`c`命令便可以全速运行,运行视图如下: + +![](figures/8.cmd3.png) + +### 2. VScode调试 + +下述是使用VScode调试的展示,VScode调试需要配置脚本,脚本配置请结合qemu手册进行配置或者使用[参考脚本](https://github.com/Yaochenger/RT-Thread-Tools)。 + +![](figures/3.vscode.png) + +一起为RISC-V加油! \ No newline at end of file diff --git a/bsp/xuantie/smartl/e906/SConscript b/bsp/xuantie/smartl/e906/SConscript new file mode 100644 index 00000000000..20f7689c53c --- /dev/null +++ b/bsp/xuantie/smartl/e906/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/xuantie/smartl/e906/SConstruct b/bsp/xuantie/smartl/e906/SConstruct new file mode 100644 index 00000000000..ed6f5b6037d --- /dev/null +++ b/bsp/xuantie/smartl/e906/SConstruct @@ -0,0 +1,61 @@ +import os +import sys +import rtconfig +from SCons.Script import * +from termcolor import colored + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] + +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +print(colored('RT-Thread root directory: %s' % RTT_ROOT, 'green')) +print(colored('Building path: %s' % os.path.abspath('.'), 'green')) +print(colored('Building target: %s' % TARGET, 'green')) + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') +print(colored('SDK_ROOT: %s' % SDK_ROOT, 'green')) + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '../ibraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/../libraries' + +print(colored('libraries_path_prefix: %s' % libraries_path_prefix, 'green')) +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +bsp_vdir = 'build' +library_vdir = 'build/libraries' + +# common include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'SConscript'), variant_dir=library_vdir, duplicate=0)) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/xuantie/smartl/e906/applications/SConscript b/bsp/xuantie/smartl/e906/applications/SConscript new file mode 100644 index 00000000000..f129b326245 --- /dev/null +++ b/bsp/xuantie/smartl/e906/applications/SConscript @@ -0,0 +1,10 @@ +from building import * +import os + +cwd = GetCurrentDir() +CPPPATH = [cwd] +src = ['main.c'] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/xuantie/smartl/e906/applications/main.c b/bsp/xuantie/smartl/e906/applications/main.c new file mode 100644 index 00000000000..d076c2064e9 --- /dev/null +++ b/bsp/xuantie/smartl/e906/applications/main.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-21 Wangshun first version + */ + +#include +#include +#include "pre_main.h" + +int main(void) +{ + rt_kprintf("Hello RT-Thread!\r\n"); +} diff --git a/bsp/xuantie/smartl/e906/board/Kconfig b/bsp/xuantie/smartl/e906/board/Kconfig new file mode 100644 index 00000000000..a6ab6a627af --- /dev/null +++ b/bsp/xuantie/smartl/e906/board/Kconfig @@ -0,0 +1,43 @@ +menu "Hardware Drivers Config" + +config SOC_XUANTIE + bool + select SOC_XUANTIE_SERIES_E906 + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + + +menu "On-chip Peripheral Drivers" + + menuconfig BSP_USING_UART + bool "Enable UART" + select RT_USING_SERIAL + default n + + if BSP_USING_UART + config BSP_USING_UART0 + bool "Enable UART0" + default n + endif + + menuconfig ENABLE_FPU + bool "Enable FPU" + select ARCH_RISCV_FPU + default n + + if ENABLE_FPU + choice + prompt "FPU Configuration" + default ARCH_RISCV_FPU_S + + config ARCH_RISCV_FPU_S + bool "Enable [F] Extension" + + config ARCH_RISCV_FPU_D + bool "Enable [F][D] Extension" + endchoice + endif +endmenu + +endmenu diff --git a/bsp/xuantie/smartl/e906/board/SConscript b/bsp/xuantie/smartl/e906/board/SConscript new file mode 100644 index 00000000000..d9603bd08e2 --- /dev/null +++ b/bsp/xuantie/smartl/e906/board/SConscript @@ -0,0 +1,15 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = ['board.c'] + +path = [cwd] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) +Return('group') diff --git a/bsp/xuantie/smartl/e906/board/board.c b/bsp/xuantie/smartl/e906/board/board.c new file mode 100644 index 00000000000..48204fda4bb --- /dev/null +++ b/bsp/xuantie/smartl/e906/board/board.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-23 Wangshun first version + */ + +#include +#include +#include +#include + +extern unsigned long __heap_start; +extern unsigned long __heap_end; + +/** + * This function will initialize your board. + */ +void rt_hw_board_init() +{ + rt_hw_interrupt_init(); + +#ifdef RT_USING_HEAP + rt_system_heap_init((void *)&__heap_start, (void *)&__heap_end); +#endif + +#ifdef BSP_USING_UART + rt_hw_usart_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif +} diff --git a/bsp/xuantie/smartl/e906/board/board.h b/bsp/xuantie/smartl/e906/board/board.h new file mode 100644 index 00000000000..21d4e39007b --- /dev/null +++ b/bsp/xuantie/smartl/e906/board/board.h @@ -0,0 +1,442 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed 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. + */ + +/* + This is an example board.h for Board Compment, New Board should flow the macro defines. +*/ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Common Board Features Define + +/* + The Common BOARD_XXX Macro Defines Boards supported features which may reference by Solutions. + Common board macro include: + . BOARD_NAME + · UART + · GPIO + · PWM + · ADC + · BUTTON + · LED + · WIFI + · BT + · AUDIO + BOARD_XXX Macro descripted below should be defined if the board support. +*/ + +/****************************************************************************/ + +/* + This riscv dummy board include: + · UART x1 + · GPIO x2 + · PWM x2 + · ADC x1 + · BUTTON x2 + · LED x2 + · WIFI x0 + · BT x0 + · AUDIO x1 +*/ + +#ifndef CONFIG_BOARD_UART +#define CONFIG_BOARD_UART 1 +#endif + +#ifndef CONFIG_BOARD_GPIO +#define CONFIG_BOARD_GPIO 0 +#endif + +#ifndef CONFIG_BOARD_PWM +#define CONFIG_BOARD_PWM 0 +#endif + +#ifndef CONFIG_BOARD_ADC +#define CONFIG_BOARD_ADC 0 +#endif + +#ifndef CONFIG_BOARD_BUTTON +#define CONFIG_BOARD_BUTTON 0 +#endif + +#ifndef CONFIG_BOARD_LED +#define CONFIG_BOARD_LED 0 +#endif + +#ifndef CONFIG_BOARD_WIFI +#define CONFIG_BOARD_WIFI 0 +#endif + +#ifndef CONFIG_BOARD_BT +#define CONFIG_BOARD_BT 0 +#endif + +#ifndef CONFIG_BOARD_AUDIO +#define CONFIG_BOARD_AUDIO 0 +#endif + +#define BOARD_NAME "RISCV_DUMMY" + +/* the board pins, can be used as uart, gpio, pwd... */ +#define BOARD_PIN0 (0) +#define BOARD_PIN1 (1) +#define BOARD_PIN2 (2) +#define BOARD_PIN3 (3) +#define BOARD_PIN4 (4) +#define BOARD_PIN5 (5) +#define BOARD_PIN6 (6) +#define BOARD_PIN7 (7) +#define BOARD_PIN8 (8) +#define BOARD_PIN9 (9) +#define BOARD_PIN10 (10) +#define BOARD_PIN11 (11) +#define BOARD_PIN12 (12) +//... + +#if defined(CONFIG_BOARD_UART) && CONFIG_BOARD_UART +// UART + +/* + The total supported uart numbers on this board, 0 meas No uart support. + the BOARD_UART_XXX, x in rang of (0, BOARD_UART_NUM - 1) +*/ +#ifndef BOARD_UART_NUM +#define BOARD_UART_NUM (1) +#endif + +#if defined(BOARD_UART_NUM) && BOARD_UART_NUM > 0 +/* the board uart0 tx pin */ +#define BOARD_UART0_TX_PIN (BOARD_PIN0) +/* the borad uart0 rx pin */ +#define BOARD_UART0_RX_PIN (BOARD_PIN1) +/* The real UART port reference to board logic port 0 */ +#define BOARD_UART0_IDX (0) +/* The default baudrate for uart0 */ +#define BOARD_UART0_BAUD (115200) + +//#define BOARD_UART1_IDX (1) +//#define BOARD_UART1_BAUD (115200) +// ... +#endif // defined(BOARD_UART_NUM) && BOARD_UART_NUM > 0 + +#endif // defined(CONFIG_BOARD_UART) && CONFIG_BOARD_UART + +#if defined(CONFIG_BOARD_GPIO) && CONFIG_BOARD_GPIO +// GPIO +/* + The total supported GPIO Pin numbers on this board, 0 meas No uart support. + the BOARD_GPIO_PIN, x in rang of (0, BOARD_GPIO_PIN_NUM - 1) +*/ +#ifndef BOARD_GPIO_PIN_NUM +#define BOARD_GPIO_PIN_NUM (2) +#endif + +#if defined(BOARD_GPIO_PIN_NUM) && BOARD_GPIO_PIN_NUM > 0 +/* The real gpio reference to board logic gpio pin */ +#define BOARD_GPIO_PIN0 (BOARD_PIN2) +#define BOARD_GPIO_PIN1 (BOARD_PIN3) +//#define BOARD_GPIO_PIN2 (x) +//#define BOARD_GPIO_PIN3 (x) +#endif // defined(BOARD_GPIO_PIN_NUM) && BOARD_GPIO_PIN_NUM > 0 +#endif // defined(CONFIG_BOARD_GPIO) && CONFIG_BOARD_GPIO + +#if defined(CONFIG_BOARD_PWM) && CONFIG_BOARD_PWM +// PWM +/* the board supported pwm channels */ +#ifndef BOARD_PWM_NUM +#define BOARD_PWM_NUM (2) +#endif + +#if defined(BOARD_PWM_NUM) && BOARD_PWM_NUM > 0 +/* the board pwm pin */ +#define BOARD_PWM0_PIN (BOARD_PIN4) +/* The real pwm channel reference to board logic pwm channel */ +#define BOARD_PWM0_CH (0) + +#define BOARD_PWM1_PIN (BOARD_PIN5) +#define BOARD_PWM1_CH (1) +#endif // defined(BOARD_PWM_NUM) && BOARD_PWM_NUM > 0 +#endif // defined(CONFIG_BOARD_PWM) && CONFIG_BOARD_PWM + +#if defined(CONFIG_BOARD_ADC) && CONFIG_BOARD_ADC > 0 +// ADC +/* the board supported adc channels */ +#ifndef BOARD_ADC_NUM +#define BOARD_ADC_NUM (1) +#endif + +#if defined(BOARD_ADC_NUM) && BOARD_ADC_NUM > 0 +/* the board adc pin */ +#define BOARD_ADC0_PIN (BOARD_PIN6) +/* The real adc channel reference to board logic adc channel */ +#define BOARD_ADC0_CH (0) +#endif // defined(BOARD_ADC_NUM) && BOARD_ADC_NUM > 0 +#endif // defined(CONFIG_BOARD_ADC) && CONFIG_BOARD_ADC > 0 + +#if defined(CONFIG_BOARD_BUTTON) && CONFIG_BOARD_BUTTON > 0 +// BUTTON +#ifndef BOARD_BUTTON_NUM +/* + the board supported buttons, include gpio button and adc button, + BOARD_BUTTON_NUM = BOARD_BUTTON_GPIO_NUM + BOARD_BUTTON_ADC_NUM. + +*/ +#define BOARD_BUTTON_NUM (4) +#endif + +#if defined(BOARD_BUTTON_NUM) && BOARD_BUTTON_NUM > 0 + +#define BOARD_BUTTON0_PIN (BOARD_PIN7) +#define BOARD_BUTTON1_PIN (BOARD_PIN8) +#define BOARD_BUTTON2_PIN (BOARD_PIN9) +#define BOARD_BUTTON3_PIN (BOARD_PIN10) + +// GPIO BUTTON +/* the board supported GPIO Buttons */ +#ifndef BOARD_BUTTON_GPIO_NUM +#define BOARD_BUTTON_GPIO_NUM (2) +#endif + +#if defined(BOARD_BUTTON_GPIO_NUM) && BOARD_BUTTON_GPIO_NUM > 0 +/* the board logic button id, in range of (0, BOARD_BUTTON_GPIO_NUM - 1) */ +#define BOARD_BUTTON0 (0) +/* for gpio button, define the pin numner. if the gpio pin used as gpio button, it shoudn't reference as BOARD_GPIO_PINx + */ +#define BOARD_BUTTON0_GPIO_PIN (BOARD_BUTTON0_PIN) + +#define BOARD_BUTTON1 (1) +#define BOARD_BUTTON1_GPIO_PIN (BOARD_BUTTON1_PIN) +#endif // defined(BOARD_BUTTON_GPIO_NUM) && BOARD_BUTTON_GPIO_NUM > 0 + +// ADC BUTTON +/* the board supported adc Buttons */ +#ifndef BOARD_BUTTON_ADC_NUM +#define BOARD_BUTTON_ADC_NUM (2) +#endif + +#if defined(BOARD_BUTTON_ADC_NUM) && BOARD_BUTTON_ADC_NUM > 0 +/* the board logic adc button id, in range of (BOARD_BUTTON_GPIO_NUM, BOARD_BUTTON_NUM - 1), if not suuport GPIO Button, + * BOARD_BUTTON_GPIO_NUM should be 0 */ +#define BOARD_BUTTON2 (BOARD_BUTTON_GPIO_NUM + 0) +#define BOARD_BUTTON2_ADC_PIN (BOARD_BUTTON2_PIN) +/* the adc channel used for button2, if the adc channel used as adc button, it shoudn't reference as BOARD_ADCx_CH*/ +#define BOARD_BUTTON2_ADC_CH (1) +/* the adc device name */ +#define BOARD_BUTTON2_ADC_NAME "adc1" +/* adc voltage reference */ +#define BOARD_BUTTON2_ADC_REF (100) +/* adc voltage range */ +#define BOARD_BUTTON2_ADC_RANG (500) + +#define BOARD_BUTTON3 (BOARD_BUTTON_GPIO_NUM + 1) +#define BOARD_BUTTON3_ADC_PIN (BOARD_BUTTON3_PIN) +#define BOARD_BUTTON3_ADC_CH (1) +#define BOARD_BUTTON3_ADC_NAME "adc1" +#define BOARD_BUTTON3_ADC_REF (600) +#define BOARD_BUTTON3_ADC_RANG (500) + +//#define BOARD_ADC_BUTTON2 (2) +//#define BOARD_ADC_BUTTON2_CH (1) +//#define BOARD_ADC_BUTTON2_NAME "adc1" +//#define BOARD_ADC_BUTTON2_REF xxx +//#define BOARD_ADC_BUTTON2_RANG xxx +#endif // defined(BOARD_BUTTON_ADC_NUM) && BOARD_BUTTON_ADC_NUM > 0 + +#endif // defined(BOARD_BUTTON_NUM) && BOARD_BUTTON_NUM > 0 + +#endif // defined(BOARD_BUTTON_NUM) && BOARD_BUTTON_NUM > 0 + +#if defined(CONFIG_BOARD_LED) && CONFIG_BOARD_LED > 0 +// LED +/* the board supported leds */ +#ifndef BOARD_LED_NUM +#define BOARD_LED_NUM (2) +#endif + +#define BOARD_LED0_PIN BOARD_PIN11 +#define BOARD_LED1_PIN BOARD_PIN12 + +// PWM LED +/* the board supported pwm leds */ +#ifndef BOARD_LED_PWM_NUM +#define BOARD_LED_PWM_NUM (1) +#endif + +#if defined(BOARD_LED_PWM_NUM) && BOARD_LED_PWM_NUM > 0 +#define BOARD_LED0_PWM_PIN (BOARD_LED0_PIN) +/* the pwm channel used for led0, if the pwm channel used as led0, it shoudn't reference as BOARD_PWMx_CH */ +#define BOARD_LED0_PWM_CH (0) +#endif // defined(BOARD_LED_PWM_NUM) && BOARD_LED_PWM_NUM > 0 + +// GPIO LED +#ifndef BOARD_LED_GPIO_NUM +#define BOARD_LED_GPIO_NUM (1) +#endif + +#if defined(BOARD_LED_GPIO_NUM) && BOARD_LED_GPIO_NUM > 0 +/* the gpio pin used for led0, if the gpio pin used as led, it shoudn't reference as BOARD_GPIO_PINx */ +#define BOARD_LED1_GPIO_PIN (BOARD_LED1_PIN) +#endif // defined(BOARD_LED_GPIO_NUM) && BOARD_LED_GPIO_NUM > 0 +#endif // defined(CONFIG_BOARD_LED) && CONFIG_BOARD_LED > 0 + +#if defined(CONFIG_BOARD_BT) && CONFIG_BOARD_BT > 0 +// BT +/* the board support bluetooth */ +#ifndef BOARD_BT_SUPPORT +#define BOARD_BT_SUPPORT 1 +#endif +#endif // defined(CONFIG_BOARD_BT) && CONFIG_BOARD_BT > 0 + +#if defined(CONFIG_BOARD_WIFI) && CONFIG_BOARD_WIFI > 0 +// WIFI +/* the board support wifi */ +#ifndef BOARD_WIFI_SUPPORT +#define BOARD_WIFI_SUPPORT 1 +#endif +#endif // defined(CONFIG_BOARD_WIFI) && CONFIG_BOARD_WIFI > 0 + +#if defined(CONFIG_BOARD_AUDIO) && CONFIG_BOARD_AUDIO > 0 +// Audio +/* the board support audio */ +#ifndef BOARD_AUDIO_SUPPORT +#define BOARD_AUDIO_SUPPORT 1 +#endif +#endif // defined(CONFIG_BOARD_AUDIO) && CONFIG_BOARD_AUDIO > 0 + +/****************************************************************************/ +// Common solutions defines + +// Console config, Almost all solutions and demos use these. +#ifndef CONSOLE_UART_IDX +#define CONSOLE_UART_IDX (BOARD_UART0_IDX) +#endif + +#ifndef CONFIG_CLI_USART_BAUD +#define CONFIG_CLI_USART_BAUD (BOARD_UART0_BAUD) +#endif + +#ifndef CONFIG_CONSOLE_UART_BUFSIZE +#define CONFIG_CONSOLE_UART_BUFSIZE (128) +#endif + +/****************************************************************************/ +// Commom test demos defines + +// i2c +#define EXAMPLE_IIC_IDX 0 // 1 +#define EXAMPLE_PIN_IIC_SDA 0 // PC1 +#define EXAMPLE_PIN_IIC_SCL 0 // PC0 +#define EXAMPLE_PIN_IIC_SDA_FUNC 0 // PC1_I2C1_SDA +#define EXAMPLE_PIN_IIC_SCL_FUNC 0 // PC0_I2C1_SCL + +// adc +#define EXAMPLE_ADC_CH0 0 // PA8 +#define EXAMPLE_ADC_CH0_FUNC 0 // PA8_ADC_A0 +#define EXAMPLE_ADC_CH12 0 // PA26 +#define EXAMPLE_ADC_CH12_FUNC 0 // PA26_ADC_A12 + +/****************************************************************************/ +// Vendor board defines + +/* other board specific defines */ +//#define CUSTOM_BOARD_xxx + +/****************************************************************************/ +/** + * @brief init the board for default: pin mux, etc. + * re-implement if need. + * @return + */ +void board_init(void); + +/** + * @brief init the board gpio pin for default: pin mux, etc. + * re-implement if need. + * @return + */ +void board_gpio_pin_init(void); + +/** + * @brief init the board uart for default: pin mux, etc. + * re-implement if need. + * @return + */ +void board_uart_init(void); + +/** + * @brief init the board pwm for default: pin mux, etc. + * re-implement if need. + * @return + */ +void board_pwm_init(void); + +/** + * @brief init the board adc for default: pin mux, etc. + * re-implement if need. + * @return + */ +void board_adc_init(void); + +/** + * @brief init the board button for default: pin mux, etc. + * re-implement if need. + * @return + */ +void board_button_init(void); + +/** + * @brief init the board led for default: pin mux, etc. + * re-implement if need. + * @return + */ +void board_led_init(void); + +/** + * @brief init the board wifi for default: pin mux, etc. + * re-implement if need. + * @return + */ +void board_wifi_init(void); + +/** + * @brief init the board bt for default: pin mux, etc. + * re-implement if need. + * @return + */ +void board_bt_init(void); + +/** + * @brief init the board audio for default: pin mux, etc. + * re-implement if need. + * @return + */ +void board_audio_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __BOARD_H__ */ \ No newline at end of file diff --git a/bsp/xuantie/smartl/e906/figures/1.env.png b/bsp/xuantie/smartl/e906/figures/1.env.png new file mode 100644 index 0000000000000000000000000000000000000000..64f009ee845922e7c387653570c947a586828e15 GIT binary patch literal 27810 zcmd?QXH-*B`}T<_8k7=RKso^unutmlX$igeUZjhN)X*Wc z03tmUB@{ylOwi|f=RY$a-Zk@evQ}1-bN0E<-uvvm&-q>VmG`>Z>NJ$hlq4i1G#byI z>XVR=B1lLsp|6q?w~8OH`g+6a5uE^bC&x* z^m*)NE$v^WmcuLgYcROFG9b0#`Lwmwn@&mlruDwS{c^rqJ~2!&>I`=Oc}agoSs)~1 zFc5}oU1_CbxJ0ZjN$*6*85mn3D~MA+pJ{bg3B9lcTl=!h}C2Lp^m#3towV&OQ3^%ZgG4 ze+zk9jzk@W`ErJ=8F8d@pa0UNTIo3DX#7*@=DOoqu-O4ggVapDy?jyD-^?Wwsfq&r zxRM0?vn{c&c$UeS?#S<>HPE5(8!iSo2Lu&@Gv)=b?SFdqRj@ZMju|m62?ba>$L8J}=f{8B{L7FGac+GW*z~9Nc=cQwpOmV9 z5mh~i@gi36bED3+U;CI8L~;>5%yeiCycH!=5a2U^0^YXBk&xGf!=BIjQY94S9%X_p#jQVoKxMyHwhX zU>i@XNw0L{_Rdk~m0J?0mFH8Z67OkmqI!=ze%EYpmu;Ycr?tZ=9rB#ObIy3h@$q4o zkDShi*C8J1__pMZd;5o^POeA-jr7lDli^+#B4*CK4qdVz+bztbt8Ex)S&4B5tSfP97|3yPP9WViiUul7<5}??MxW|k9SeiF88mw;~c|udEQ;20bf40Ig5_S8cE;2K%bcgR` zXJgN#aOhDEX*UTri>-ABSA2jJoYyr-8$D=@g1se0?!`jQR>p&D75-lKwdT9iX*iSp zM5u6|CSTUzt4-piZ1fRe;63vc`+I>Op~yPdWP={=&jww`Em^MHIGI@R*KF*)w>Xxy z|2sIXE2#d>5E6l6=DSxfDif@B!{zV3GS2D0J@rDp>e|JQsu*kfi%;uxMdlqk*e_Dh zWwW2PnS?S3#l_|}?wc+*N$Sb*%)}o`mAOoU7hAu`{C5UkAuc?`7e@bh=Jb09jvgzN zS$RHQnd+N0%thQDY?WMWkKH>vLwf^-6N8Kn6)#F#yY}63Y4^n)HdmhG_`{6OhuL)c z*C3^Y_i@YPq4IwJem zBO}EgWC(w)dtw#3Pv`4eGv-;rF(;{&in*}!s?%&7>+co&)JB{J_Ffye)Ud&&GQ5Yg zCO~YOyW?Id(rX=bxEG-q@ige?LotSnv#d1?b{5d`v@P{h34zH|U1`?jq?>k`a3`R_ zZ~nUq0vr{xj+fiL04|3fQ>~AWdW+m~lTb9xx+DAsDkl9}a%7mF!fF*COL@N<+0MMlBVuS*Oyn~RSF8&flqXdkBs z?_FB=bu#f%;H6Mg{T>6eocB8t^EgIZ+2X^kPtX|KgtJy;SrisW2I+eb;tx_mwJVgJ z{hhH6Jktl4HTTY6kEHg|5gUkN)pK7+VFg&GGwq2175SRYL7&M*7uM|@Z6ftuPA~2l zBnKIPTkQS17-;pHiP6@7QDapMm<&2Nj{P8)1#@0#^$&T)>YFzU!LpBlttV^fG(V_bK1cpn!;7b{wyoXvHPy81IF_KUn zHM&1-!mEAUwQA9c9oZ%}H2>zFl4B7Q7&|W*VL%rBb{tr11+bq$M*x$m8K+XR{uoPd z9=B=Gm8RSOd zxqm0#|6|Jh_uz}!aQk4Ow_SvZ7ar?y=}4Nma=LihiqGDg@%M_PF7nOieXedW@am`G?N2*D$JY#MH?u&MWr9VGtJffYJtFraC4la> zT1RE>J~BP^fbQrT?|~}nBFnkipI1qO7i>b2x-YBsn*{R5G$5}|T~sfLUR@eDz;iMtf}C*f6I-V zp_3}Z4#7h*cF)Zfg?)T~VccqSS%zPF--@tZS@5ngRv!n0?3oz z2RV(dC%zBcf)CS>k~k!vARQ)61FVs^XFNZxnJM+8%H2Iye6-v_n>=`6tas_H`6H9? zspgOZ%9Z2jfeb+NR8h{|t#puD#Nd@Y5iyvqcJg71T}{(9ysI(86kGUeP00{0=yiD0 zrXI|A$lEci7?6KlP{lEr$|o7cVXLxwh^raQVE?dPf{+egx{xWdI=4L~1e`C<(9DXK=-t?HF`dDD`2Y(U6wQ<$MZ^fxR*=-VE<&(L{2*073J zTz*HcyA!;>RInri`&?&1W`AOk;4G;bv2s?xF|3Tsw}8hPaL4rJc`j`&o!s+Q@M?eu zULyhP7utK8*?*_&%>|7uqRAgg-BO=w>dfWSouYb8t{$djK(QTbD4Cp|nxx@f;Rwo_ zX&dUNUt^Vj)H>=)Gc+i+pXPfaJip!k-e5bSdk9e@=Noew3S#aka9k z@y=U36@0#!J-IluM`(Ne!2CFT4c%C7k9~z!6x@f_ml1MV?5d{ZnsuVhItchy$Y7w8 zY5m&xLF?#hvG?LS!@(Q?1>5k}pUYN+?@+thc+2=<-;CXj8IS5GL~A?jmOI}p8LQN8 zc807w%NqrIJEZ%-^Z)D2fvfoL1F)0=fikt^CJNaCQu6DD7{|K%l2Y(clb`X(Ey;_G?0F_Y+V_@ zZV6>K#8PwRwe$mj?44lq2D#G_iuJV~?cxuKlkvb6xiBaKd2pm=#B+W-=~*V8mSp6K z=k_SKT@#P%VvIv30~+Y!h71jFFWtKp>{I$haGp1>N^5F2hVHdjXKizknKC75SB)u> z-aObaJW0Ml2Vg5HpJ_I=hVCQN0YMTmg@%FKSE0?XjVFD1gxEsO5N5sw7zQ8n9-8Y% z8}K*%2cBb=g+L310a+k|y28uNI&XRrHrx9tt>0oA?9!1p47y!p2LT+V*-@8Tt8ff! z>$(; z$;p0cC28B+V)%*0m<&uo1@J^(EK!byW+;;?wPQ6VuPK_`)Sv zK2n8}nri_oc%^rcEtojRoLt!P!iUQlz+VCsi^ps3yLDWQas&2EbOG3>N%_VP?G-HV zVv`CR1?Bd-TDY`cRvTiSA-cQzbt%*=YI=3Sxf+Y#z8u3{9v(u%E* z^woY=+ktP@_lx;zWrKfcuHZZe z&;-7V7Ax<*VDM~Q6y9Ddmagq}6JpNXjoqGR0zMm(1lWWrz z%eIrLaRLG+?HM1tv<=!#R&r{s%vS3{1ssjd70w?wvW-l+K1a-#WQAa@Uu9|^RYM1w{viRdouCIcuOp+6CI;8rANk*V0p~w(G_LD^R z=kqO^f%b)MkzOoKohi5_Dn{Cb2XeD7k8);Z8MY)vs43ly;jOpzbXgJ>@qLn+Mj z=MmOH-4gkSR4w^fFjPyqik+JtUIw5DU+IRP`K+W@LS2&{x_aGXL`(}Izr*^HhMDP) zQ=+C6WO5;wz#ay(%;l72X%u2C^1|Z%IORNnP3z2P) z{h;axs`nte%r9;;Ke`V#p|8|=j(nnn8t3HOI_HOv`G=!vn?2K|zBrgzk6Db1V(Nbk znexve@cDCZ;A7t>`+c>7&K#K*vnws_6pP%Q#wH}TMbK|*uhplo41a3vVPO-gZv(h+ zZOgm8h^&++C#icL4F{lozhOLc5UAM>DrxE4%^1_en)9s9Bu{ek_j3&+{Q8>9NA4a} zZU!EHCacG7?Q*}J6eubww5(oJ@%|{NvwGQxCM6ADEjOyMVwn_R!jlgrAvGR=cC=C3 z$+TlpBs{KJLg#8Gx7IO_*{D&KgBZ5u8|VANI_rHmjRSZ_0H%4Kq}V-N)0|mG}KVc`S{D8CIo>`tMU=HBJ|IJgn%OLXQPH zmrP@Kg5m;o!%X-$=$t}Z*Fqrcm@Atn>eS=m>7`kCbx^q0{$426SBl3jnzD0pSNy~936);`MlaUQ6O*1aUF_;>j zB12F_uYZ^-J>9--WuRa=%_c$`SLbV;758iD!AS`A$JtA5W`9y+L%E!Xdx7AU$%4X` zOAO$9KNNa_Y^3%dRM_alIQcr>a`2CZ;~ye)cTy_ASi1RN4f*S+90_;Bwbur-6cK2w zp2yuptlTt-Wo^B;ZSHI`L+AS;;IThvf?0{(Htv+EprHq|oPEajB7u_cV zg+jGq!@D|J=tpEgP5;h7Chf~ns9_u3&OltHH=u@oiCg1Ov;{W5&!%EOHN6Jy6w+vA z_I*T3@$|CoWpsz|e2_2-R{gpab!*7ey(7^Fu5W|ycLK_B`&U)v?OfGd;A#n7{k+9S zpST!n0Ht1+-q<3dANYU6<7_eq7~bDsL|$rL0T)CKnR zBsKkdE$_MRvJrs`^xU-e8cE{(ECtwl{KcArMU~C#32`X_w)-PQZet6#rdNU`P^?tR zt`wD_Kh{VKmW@JL&V5&?$0TuGh<$>aPTyoHOx;Q$FEm36X)8X7SUeB0u(T*T!U>V<5CgKk zzZ7}_c_dS#|CAZ){|Roy?ZMvvl`)#-rni&hp+EPh_1JmnE{;im1OJcM_}?inBnzi_8Xdv&O zT9GBO5aqM~IZdeaoNB;sGVOyT-fmJ!nE*^0=N@WKxQIbQO9hoIT(#(XFKM^arm~yY zWc@m<%=;A*v^pOp`&YMFsu5Kh8T_NcyD3G=zpk~|-N`VJcCJa^^XA20gv}|tg18S_ zZKVebB?PFQr1Q#`f7aV|mvPqagUC2vNI^;rnwLm1@cbVrt+ zV?QS(h-!oW_Sic+k!fnWTXouM{xyQ&jwotGNQls{&wp$8?3KhcH8~|;FI%bq>#VG0 zr=~7PW!ZZ=Bc^|M-!!F_R3RlRpBeFtRc31Soo2gJbU+;|d%^C(%w-gaGbQC3E#o7@ zI_U@e$e-HU(PEFT6Zer!yi%P0YlGC*5dtY0gNdLohp)%lV^Y$KhABM<&`8=52Zm3xs}Dv=S)~RR zE&FK1bKP(L?|Jhk=dBG2RxOGnDJYpOHWhZ?goIq2?`{G_)2(Gy1=~(_NYo(OY8rHt z##_|v(t`hXiOdrsi(bSh@zhI3{SyIYZb|8gCJ+gI?scNNFGq? zl)W>cFC@=jsLh(tCmp!$hqrUz%yQw#lr$J;Vr5H4!qhT9cG0oMS@qRS;#4){K#e+_ zn?x0Jd$Sb|FnY)IqE_`tH;9&Wt!K4Qt-r@Q{}?t>&ov!)UXnc7{a!!?r$p zdVRi@y#Y|n@v|)Hm5C|ib;fR4P%LfgwH?&66Jk#W%v#kll^1U%FZYr|UL!?~R*d@T z_kYFMNbDv_Req-^kCP-6&D5n2hs`$D%ob8iDoE5TcHd)~sp+nhNonaxYz*oL`RI$? zc6^_+|E6Df-4OP>R<#;PZUT-Apj@}ZPn(KWw>=|Dr7|iJlP)Ef2mf4x97Gl0<`GCX zB2v2#gH*pfk?}k8I2@eBKz4yW+R{6$p=72lcDb*w4!L(vdZ_cqV3tr95L1oB;0`lC)qFez} zw?dg?a!$$xF`-;OtGv?C4W;E8?17^|iCtNDH$^j&&w@2T6W}rH*wj zE_js;nV(7Xm-ryfa`Cl5a&^gGdD4L=b0+0Krbvp1dtP>mn0scQ^~PHxQm-f6Qd?Ov$cYMTmqXpgeImh^=t2w`_D?T2 z72uq#-$2 zw<{3NOEv5?wOT#lW#C{Df54w^1~6J`*UjZ}T4RC?O}GkedKSD9h*vP;S#)akV>+)rN+{`{r2_p6;h zOO*6k$=b$b@ZUI9LWVXL5KvwS+&wKG8=?`HNVM-_vC~~wEPRr6Xy&2g&Rg@V-(X$OicK0|Z<=m<_AS!M^l*==r5gHeFs-R{rqGFE9&T86d zW4QDY82k_3)q*sHl(yiE^21#Va`AS>M(WIm^_C#U#2pGTGX1NL@YRCb-J4-{oi&*$bl=Y64eSxnA!EBhd&L@_+u!CIezl5;)xKI*h!pB~ z=?~LH@fmv_N4qX>o<;38uJ0uGGgpxxfnIDK7eUV!rW+=<n zk3y_&EFSY(^lIi%2Dx*x3|kpCm4}*K)h;v5O!6#Pk+1st^(Xu3DxjC1?bABQ8#H=F zhOGp@ONM`VbK}KKCev6YRrlU-ULdqq!2K1HC@KmuzjG9G%6v@8m*TT%`r4R%rdmwj zb4yZvfj_o5%k#mJh&10bKr>U8pWusScDkQ#VHFSEjyV082Q%FE3Gh4ig;5)ZP1ms_2Gb|fJg zR0UVgOypi}CfKwpJTG}Y`ZCOyq?m@Bv@I`svNfy10@jV|kQkG?2j1~F{m9AItX@~F#2v9mahg)- zNz|K~VhzFGFU*a&T^sy?wLG9=hqyc&KMh6pi3tCS4CtOIedHHeZw4R4i&cIf z%Vzl#wzq-s)JA3&hhQ56p0I;eG1s{_sM8y5;Hlafk4P=TiP8hW!8zvLwgtT!0d6R- z8;g}ClYgPJGg|2BXnJ;q#Cmt5>Qd+vXrOKCyiLoaOL-vjd3Pk=w_qA6LgdJ*|m7 zS&Fh}MRn9WhQ>$Qj8Aj$^g2IxcD1$L$la!)tdketaz~C9ia9_oDnPqgWo>YcuGS4K zu6mcWGSl?siz)LmD`BoH(Vf;jlVL@V=}LXo`s*IbIcN@YK4;}iVUipWNFUbq%>2a@ z$+a`w`f=>uV9TYE`1Om&Ocix_zDf;LE4G=X1Tyy{#$j&uPc!gjetq-7fou$I)z6*t zKxAN{-B{%$Ac>bCBM@|%WJFU&c$%8=ZPTAz!6$@4$>@Qz{t%51gpx0e?#y)|;z_zHNnrUVLx4fyGg`go0c<$qz z{T~}@>muBV#9^SEa(b#yNkbA;4;f3viIb0X(gXo80fIjsM`Tl8YR7Aq}YG|Pm9oJE~#q<;p!k;4QycD)WVQ@ z*H}U3aoY(le}Aw027|@MB?G6m+{f8+DbL7k7@$6fz1<6*uS!1^8ioY?5A;_4FM6j8 zdoR_uOcj;64^WQXi{IsJ;;i8CY$v2j5j+aRDvwUou%>XZXW~Wj3kK|O#mRKHSad*GYvMZN;I8j6Ad=C@do#cW^T80;>( zTWCQw>-$LUP1kCdg}U@#n`+Q)FCPR&Zeo4c;^a=1zOQcK(%M7aLkg1Ig4Pmc*#iBc zHb*+@BS`(W_8tG@P59o2#EGztjZt$IiB$+PisN9s+{0vJ)gPB{Ow3kUU7cz=`l6J5 zP&!{RvhTD$T(*gty|@MzqXk5+L>F2CSk1mxlIfJ7G0C0r5w^9((c39?`%|)>{KWL- zNV!ZMk*;;i6~+Aw_Qm+dsdL87REB;!)Qw#sibN!yWW@BPS8j-RjS<~-TLu4vEO~Qe zu3n8oa{<%+F!e-QJx*HU^?o8|M#4K9)xf#Y^W$;uEtHMBQgPWbd20?%fEa_8$O0n( z`Rfu@i2 zU?R{(%xhenCKwLC?Lu4eV(kWpEUh9h%JCv(yMoB5WB;XT`>eYcB`$DtEv^jsla~5mzRA&7UpVEz zIIUxD_P0bItV;UxnB4A4UX*VD2zk}*FHKY5BHj{6Na|nE62$@AX=-Y(>_`sZk9Y6z zIHX67B>nZ5+?=5yo_&?JkZk9T+$ev#1ZQhVDDl~nkDT%^y+1GxLv{v4phH5Q4|@@Q zYJdE5LDXMtbT1;`4e7S_d}a(MqA&Aac1Q>xgp{mL)KsJHFKSkoks*k(g}rqaR-TCT ze&eDFBCD+|cNTj8bM)JM>sp{O&F5HIX=u(dIeE$dV(J^n_uaJ|*Rg{kqw| zt!w|o&U-sUa6Pe}l~3bINg<&Zd$aVrh~s3^2x@=6C{1z+KhpgRyx$xj5l7ge z^L$81hAgTpR#rn4VxcW-DaFL|*9!BMnM#tvq&ZeLRg9F>2%hBm@IM{)9GkS@GZ3)` zW!xfaKmm5(?0>2HG-|(#k(Y&i!4&wzX#}x`d>&+N|ijWpUUyy zSF3Y>)&%7(YSlSDYbaTq>gezu(b{^3uE}U~ttbp@B-n`Rixc&h6q^fILJ}P^ApgIR zl&AYBq2G=d!1_s@s}T9due&q42Ikj9eMRhflb1d_n=HSW{qwX|Y*Xu@WzG}|0pw-- zh@U(~mricR1wmeh5l;;H63C;|+a(*5|Ez1fq)~4aQ`&%i|63eaAfv4z9tGve(T<)gx!_@n+=UCE<|YwOl?W4r^K zmbs!C_$&uo2>K%}av2!@2U(L;2?MN>HuXO`XhXj=^gz_TRdnW>ldPpzzadmHJIY7Q2zL{U|qX=e!bA-mY0Jy$95%1Bt#0 zf})kR?ZZWfJK-%Y<=PRa1Cf+YkNQ_@__#3~b(XbE6)%Yht)*J7qgReCq4Ci9(dx3d zWwxU|ByT;&m#<#(NvG?98+0kc?tnw4I(wF3KH`j$E2*#Q7X!Fv4kF5 ze8n~IR3pl+8ig?s_g>(0Ju)5pg|QnF#5%WmRD-=`RxGV1mWs@?CXmS-g3<|P*yNX# zuCZ@O0f5zzzTc!*;2W35MRWJ}b3v`7ubawpe27|{SM~=5#P3kE+7B@6u(_3Lz`z7z zsad(3^}l(4+&cs$RWYqQmy3(|Ll+D@1jE;ZlOA|*MfaLFAli5w_{ zl+si@3ZEatO)EWR{IxgwkOu6Y36xFpRj~9k-P95u@La!18Ri+1@Aa(w737jp)%5c1 z;OFW$L-nYLYAfQ&)TgxPl$URAevRE-H)Yb@Y%lAofi$x7iaD-KJsc~f1mS(%t}(<( zpfiVdhM6Dp>!iSo%p^LM&C;U;18-AG$%a?=Oo(=oneYlE)VF|-7CouLjiBBJyaTFw z_|+ml!|&V4Yf*0y2EaI2CtOmPaGg5{*5@hr;Mfw?gMV?_`+1ACsb_%u$IJoI!?6qb zs#UTiQ0YPVwB2LmS?}Mm0coqabAl(mP$14T=pEpWhz5g{P#lq=_VCo(=(63uoDeQ@Kwm4<{m0rC2H2J0vj`ch?C`HMxGeCm5Kh1*)jWt z^dl6f$Ob_2@zxY;aq8;9Kj~uE8Feq{QF;h~?%@@8GE>Zf@1(>d+0~bzg>;W;=Y_{r zLZXXAiC|JH@tb|@0`g}4fY5^pAxvjl8vIAGHFUDM833O=nKu_98CwalMoeH{_uCJ` zW;el9JIN8TT1|6V=Q$0gI;GlkBe37=M)+=lmMVJ{-QYB7t~sO|Ci$3cuaO_<_ zH}{Ty-(Drn$h#M64%O?E11{e5))052I6UsL?SRA}u=<&eF?p==^>gAPY_BHGGfrCO ze0`qNO4VoDUe_w68JrS8Es~E%37+0bPOaVVjY;ndH_nu;blqAPGC!s{JgL3C5@VEY zmYND$X)^1O`aI^SUvxZ!GgD3+zk*Y$YIm~i`KO2^P^}do4)7H&72nQBh`c=-h@!M= zYY(l*Z*6_8cfGuhEXCve$$IT-YJMly<(*F2VZaG&5)8`axBh242Z85P>Tzt9lAo}QYTsJR9WAPz6TR_88$k5T!2p2Ts= zng=^*9TFvz5_%VM=YM#x)~D<~7^06=Y+n zrW>n!E)PxRsbnqehjvKS;#_i1*Bajg*bBp+I6uL@vV2#T;cGUO>NM)0bo-<&C2OR# zxPa@J!>BR%ZEIKCexpR(jaZuQsX^F&fUkG6Y8RuNZ^I` zRZNbdensEWhwb-{aS=n7R*ll}>ABZb`6mzQN^-Izm_VT*dEIpe5^FPo% zFG#ID4J|8|_(Qp^k6Yk)){i{%hCutA7Y4U{q>rdbNM2TV+UIqQ#OK*tWZzYCC+C~K zAr|PLxe3}_%qALZWZp~Mrb%JNQii%$u1Ro$U1bb4Yg?^tUo<{qZ5wB6R$*_CWM?`Q zYcVBIUlO$0$pyJ*wwdjUbLpgBu**`Nrx2%fV+TGdfW5VT7*{Y!QRFqZ6Al$6(e9 zB+>-Y`7gEfnv`5>>6y@LZL3EF!~jT6)D@*--wy!k;m6M??SG~z^ zzP}p!%Pd@3(QnAlAb0KTfCBz|3MJlYc*z2EutRw=pQLH9+`UhGs9e}l56bf?8q)62 zUDT_mJ@y*QwUtQ;%IKZF{I#@xs$61APDgC8<66?UbM%qZA?y;#U4fe}#7d460^5_bR5wiJ1;o=a^J76 zfZOhUAKh1ecJ~`s4>5xiwsi}fk8(&|ZvnE)ZQ%L0O$ONfYc(Tm@hR+J(NAw>=hsk3 zGo8xdg$4Uv%Q#rJ+#F;~lfO zg-r9~)DRJ;2`^++rWchT-w5>e3q~1pi7G8hs{|*uHyA?Ek)a?{0&G*l83Q1}C_@~ivmP&XCNL!ZB%LE6^!o^) z9hrS&#JdA@oMs-=z+A;M_n&6=w&pjY_p?12r>LH7jY=5DbNLWNmlvZnl1LaV;TXEz(Xa?$k=BnS7OhSW(RgDc93bvx^ zHV$6S>a_%!Kgcw$FbNODmutf#HriX~2*EPlfz8t3%{(~~S2Z!8D|l5p2LosnSqICx zZ~0M8!umkY;byW<8-ZcgL;@S$*yavtVj2??CO$U=u@|RzSn%!epA<~B78JGW>t9+` zx@R9SDZN=eouwIcoYi}~O$hlcxvWR8^hnbJUO-f5HdNo|juuD>{*?9U?^1tt0!tqq z_S53ySxMJPyChVyX29sXp89bsM@mZA0(T5TjnLikWp_77J@OYr`WTa68REQoa5a-J zh$yq|;puDzu596AHWZ@kNf`t;G)pNB*+hxLYUA~*Q-D2L!UrC4OlrNWLbRqz0MWD1 zLfhw9sOV&*wwZH4g>n^2Hu9m*QQthxucV{b|DX|Y9B(@5SV>{$v7d+A*6o~dOf>nc z3dz5c@YeQ7wo~BW6?LIVPOM>97hDh~A-Us<5z8ED44`a}W;{ zA0P;8lb&^J*#_f8<3N_?i=vq;x&X4W0*Iw!PQv9x7?b-RUa=kiSMo1t1Vv56s7qg_%mNWjZ zM!G~_2JuxD^Iu8lzmA6g4@uyQK>w$0;{OK$Dq6yj7YXja`j*h&9QQ%Sy_u4+7lqg< zWwC3XbUiI@uRs0FcAU)^ZpET6a^iVH<5-;MYeX$HvC@7uIS@ZS=3PtHqtdv-I7Q#f zEjcX^6D7?w3E7$BLAEY1P#nH@5kP6U{91U)#PfNN%31OmH@iu+3lK}jm|K!;wLTgx zI-U1zZ<{bCv!Hr!(tVBbb?6g^l^1|Oa3m{BJcMYYpP*c*8T6NE&XDxl|DD0j#w_yB zit@Q>eZ8rOrGh`bV)V4{@LoxJPXK>RgsXIBb%v6HNT+>A+5V7#*~_Lfr&q2!=Gi*7 z*{gPsAg`W0w>yU72HjJ=7JWXcHB^>Q$S{(>wZrbN%_FyG39n{cW^9*k^~@}Nu-irK z*Lt{qht5@nco$#(+E7_IM$;28pv9g%?hh2loysxB4+}Uv3i3HUe7PSyfBxm&xr~MA zI3ho~CqVPRRS}vb$~yJ)*~7nAuX$b;B>F>S4tAG`?rhtLfSN@G1u)nBmYTE$28+js zm>-rAr&L-mkydaU@xBWtSU_#DfmCWdzCcZc^N+pB2qLaV&Nn!d;wF2h;~1TT$bO+^Tf1V59sY&R-Io7YH>@`QDNf2LuZ#bN?2b38k{fo8 z5?tDol#Xj(D7MOto#tC)d^CuN8CZ$p^}8+Ae}?YTRzj$4_P&$5SwTBO=#)&g_rJF) zCQHBD44Ko#$bRUsnw&EepzSLOK=rXjQZ;)Q>lx4a=z-@h)r0LnPHh}9P2%+hD-X(u zQiwov>)Qz(Aes?8%-lvx^kNmKYBVVlyhJ+$qqmc-Q+K@*b<~MI0hs4r&8H!v+~hRx zEm(30dF^K^PPlno*eF+vU+PGO;bsvy(euH{gP)!YlKTn|&9H~~xn717B)wK9*K_F|o8hJ+zU zpnmMrXsqk)csY5WDJ{VDgvPnV;e&cRLXtNFN(-ve14$0F(uOEF`*qyWKpm}f#SHjG z2f}57%vxOSrH3i@ht~W2StX%CGOeeZmSN~qNJM|;uDYLzpaRjM_X zWTwh&?#{Gz_w|kf#xoBaW;lL3zcysJUUHO=its2y0?fvDbUGHTHuJhk8w41=NBq6q zHooOB*jghO-n8diEl@K)5O)jOI?x=NgYprM5eIY=W>!AR^piw4za%&eHZg@L(9ZDP zg%vRU$u7sF8t{(|Ct2U6t%o7T(#5=k_|myd%`(M3U>Y5YEOLAH;$i`#(Av+HyD*+3 zLH9)qczu#Oc14VvZ9;AmrG@1(ZosBS6K-Y#5B!A^>Jd)9)x8Od*uH=ax9yWSb@L-o zrqEM_M^tKFqu%=PH|1sKxZ~Ej=F_n|Q{&@*AnlBm>P5G&NfOxDny39p!ya(QDVSnr zbqVbP`JA$x(4?=>b5^k)+klNds~&%7V<+M^%n02!I4ZIz{D9jhslxKvlrO7}i3^J0 z)RIO!-T$RvgeM`|HB-h}quegp?e`Y#}#k{NM1 zPfda-C06(Oht6YeuZvm!+{h2h;Pyv)QN42)%^YS%3um9+bU`#`SY;I71E0D4I*B`$ zTbw?;7h$|J{BFeCU`I!)viQ`IaTRo-~;f$XRK0J`{%GjI4+$ebyinLb8UkcTi z3L%%e!i}-a-MasXP2)l1-r}W5Qk#_}w%2^--={`S!dG~ujZE7rw43K9PcQ|7@q>j8 z&hvZYpP!zTSwy|HEtT-5OU?2U)z0wr(0Uku`WmHw zP)1|Muaj@fYhtK6tr*CrZZ+@&F}DFyT|Qptl=XoVOiSsZag~-5Ny!LQDv+sY7Z|_g zifB&Reh;00>p$7#xq~K@EefN)`Zrkcj|o5UmC+jbbI)x;J-uf<=HyPE#x_mxRhIQ+ zYJ6=x*40?7)@1}GPQSaP=dK))%ncXOYBql?#t}$#R`@nPy|M}aB&9MJKQgE#T*sJsK{&R=B+Mcy(#n8_N_2-&k&SERJvB?lUf|R;>^I`aR%>FdwBy#lmPTV#jCW=; zf8%P8e$Tv98)`ug2{%+_WTdU*GTPa*KXSNm?QNJ{yESf6qk^NbFronmM!UY*4VIJP z!l$=%{zztwn)$JKSf(etOgr+*TzP7jRv1+2s8V@mNc0I*{#t80LMhdo;S z*6ABWxY0g5Rdx5YF(k;KaQWL7BQ<7QN4_WmbtQk_$j$n?cT_-lNwbs)v*oZAN>^qj zvBC{1J0u*P=6kqw+a0sfuJ83wcMbyv#F@AyJskQLDavC0#j!oFJ-*&lF4JyCcmaEI zAn|J4s(!J@7SkJdi(k`8BA*R^FSZq*4?soG&Sk=W&FR5YfiAD)>R&IdGki?g6{RC*ivuJlNq6oQmLQaRlHRovOmBGk`IgEQ70kJM zHrZcu-TJlwb@LfFth{b`ybD60=&Mgd?#h&Klq6wW5i@mz%{!`g@0*@U3kpo^WljxL zx`f==3R`fhhH{Ga`Y1Sibr6R$Et;-mJL%HI9(CEw{eS~xAJqR>j8{0ycxAYC9XDmg z(F_V|Flcn)z-&5BLfZ8%5;Q$Dk_5AB-a9k5+G>|tPw(~dJ6FqfhLDATLr@aZw`;A=N}KD$rBc!ZT3ZAK z4)$VY2c+=bL9{OT$v`VGjp;BbdXEuJ=QP3erHAF)cloo!B{p7l@1c*1p8dqto^Y5g zdjvA~9yqGbXeTz%wTV4jM7wGe^*rx7*q*U2+LdrkmZI|L`yOJAW+HCnV7N5jAV|>? zCx_(f71e^O7s-UAa@Dc9`}VfvR#yJ#3zt#cYpgElTHn(VUUCK}*jB#RK(}Oqt#rO! zlL*(ovr!CQPcBf`Z$$qC7k!x4=mg0)DYFXr)S>W0_V8FHP~KS%s zq_`zmgK(Ovvp^VQLPhxO=>!c%OS04bh9?4DY~-O#!`L>M{F6_Vk}6Qfn{SzXt<>kE zn87~uTf?cf{_SVEMlO_7sB1ASF8iiYg14U9%_>xK#d*Ag;;lpJ+Y~uU#~6L zPIgQ^prFz$wmPHk^MLlY0A(;IBl85N;TDZ)Q^EK^(?%U%h=n;jt8)BlXSVJ$s5kZ}!_JtpULu?g?b?@L+~&GkmE`2lh%$eq@A zh#e!$+=`;^&)>&2IW6xA5x@<};S>OL{015EGEuQ)7C zRwPZWpo1K1vQ*F!*U3nHPLIEB9WG|4FbRhDTH5x7=%3S;Y2aNZTCw5P85u6?IQ9cy@>5$Sxf&&}`3y-S9i<*3H+6_VG@q(F#?)>Yo~&f)i> z;LMYglw%iREa4YVb&E>wH=n4iuKIWgJpR?MYWwI_Q}w zDDfxzxY_t1-FNhw4z?HSpoEE&fjzD!JGoVPHrhmIj{|Mw-=0KOJT~-$UHv_}?$GgJ@QZ;&SZT~x6 zPzb4coUG;RnQ~+7XyfPlkJ#nCs*eurlY3(rG%MYMa1f;)BH=(>gE|sdDlztUnuOIA zltoaj8pk#L<)G^D@P#e37G_bltGF95ue>wac#&lLD9)Z)NLa^VQ%!OFaZWJ*ulI8IVBLG~qDSi?#%`CstsCi%%6OEdx9Lf4 zJ1%Kav@)AF7i^b)bOWZ{)V$q+eb@G|&4wrIQ`{c+Z`rW6c89RPI*5TAuR&BA+`ST7 z+ujzHvDGPl%W9fMy>$2}lKy1lhJw{+M*ow=S@ZAxJO3^bh5qZOuV+%lRt(cUqUa)5dwfk5&PMyXutx#y7$%^UaEJ%Ez}Hp~&K5!*R=A+d7-6hq zU1VvEBw6;w&97b%R8M`O;}TS*ROmNIt+=n>t)I8XEHM2$Yg-pAWDX5kkK` zUc!zYTq&0nD#s_1Q$}Ujv-=YZC5IBm+tCpDjv~(XfTt{^kpq$VtaQs3>fy}t915i6 z9QnK!J8T$Dzw0IrLWj(JRwmCB>#{GqTl`DB=lj$1uzto3c36iV>l!-N(f;I@ZhxTp zC-Wgc!5~0Dg3mv#frs7`{wWw4jAMTg^7_1K?W3XhId*<8#U(YL;pN;&;a42|24-?wZC>Jm2 zo~G1fV`pFkyn&^Xfuyie9JR3LDeohTRB2Y*z=lQ7E=2>=LzPw=TNGd3z^? z>3t;O{I|Ebiul=e!lCI!UQ_Bc zYJ@6|z>)o_>Zw+T!{x7rzETKJr$gBJmIpuqad94^M9Q(tf ziYl5nwn@jU9F{tGH>YHuJ+yqHv36Qp^EKDb;^m#D(UNtI*MsgoU4$OZ+(*R#=W0eA zt0oc~TJ+aL(vHm&jSV+-He@4=UX){<0Uq2Q+zH5GWW*wTo_fdI5w~plPp09zy)_v<8A>_D*MjE=145-S4QPF@H|6V8_ph zi02PmnfI~CSgd(JCjw?oG)T_Qo$5|IoQ}uW*QNAuc)2eraYgw)?4f8vr>{=s7=TO3 z2#F;908S3=;Gl{&my@mMP0<_|1D9|oo81AjX`NmeKH)+IoUfj2#7pre$>wk;Wi7_f zPo2@1+S{2iUXko&7&vc9(UK>>a(nQ=uhJK2@V?WPN~SRBKWJIv&(?nl8QCzDNr)v;b^y zD5{71cWoydxY#clFEWi97ZPsyHx?jGfqQ1jE`Y#2y2jEv3nCdn_>T25yy;Inl%euuNAe`&rXyX%y7A3{lx)Av__(=Ck^=bnhL*iLZ{7 zLry%6MAe@MD9)`=t}&9P8s-=bTDyRYFW4{3^{f5*ZP zx1{k~&tBZfjFzd#vF)8Py-W&Vyw-j+-ZmlY+MQ7#Ax~G@n5Gg%-|rzB?3;!GrIISw z>#7%~K6^}BYVUh!Z{{JZ@aT|IK4gUXqe6JVI9_k>I|YasK+!caTzUDXe6B`_c+kIkFMAsk(o% z<<1|N0J%N-ec6DC_I>Aq{`vSjKh1eiLzOMigaV7Ywp^aT+i3X_aYXuhIRTlorQa-)Pp&(pT4qE$GfxHYP&3^#Ri;M5A6V4c&QOSgD3V>aBWcg%z_MGMXr=Q zDCkVO+|V)-#E1Prn^EBWAWm~n6p|A&akZ0K^K!IwUC6lW8CY12p2u}2Of2L~vF-gz z1>~A(Wxv#Bi{bEha3k{B5;|MBS0zYyyk6&rXkzADIm1MJb!^6U?fu16L84feG$V~(eI{q=LO#3Zo28OUK^JLdoHK>7 z(P$449r(>#Nt1vT;*he#Y6*J;QocxKNE}q0z=t99 zgK7I)C0It7IZIGXpDz_G4!Z_`)%2 z{JAHFUcw2U?SEi2R+{&Nt=!c1ReDOz{2)YV1amhvjsUs!G@B5SodF@>eep;G zd=LJfDLF;lFTsk4UIfAjE=IJQ>*2A8?Bxh!^FjL|-M&*$C=3sIGUC)iJiumk)F4*& zSG;Eh1oFL9Hor$gK6JvFu3LU%W{J}T2|X_%JM3ck0-*(Or>g%DKi>cW;`gHoK~za7p}obr2kQdR(P+QFNg2Dznrnoi9w5qq$Q>CV6) zr?y?ToC9m{Ppx&^Y>ysYA{iMsH!%isdHB-Sk=I5(B851&rS(P>Uv59OY+`B{(1Ey4 zzi%^Wn+&E0(tOg{#*vz-(!UV7tBSVd`NC|RM{J&NBl6@z^0z4}fQM=N9yLUBh|ccxCK`^_;CG{kC^5Fjt8iANHT zyQ3Efp+EM!U;~4?m;(w@DpJjt{}8}1TbZ7cj-2N$#|+p?IHpGfz z^|5YC?^zW1$?q!vh%=c<&_e%*XNn4)u?flSFKiZ@mnhfw(btCVIHa@FkH0$KeF3yP z>;l5p2Z{sc6?nFmt~$&VB{D2brB@9&SWli@vQD@=zq$GWRJv@ml+9hQ_I)P!{ofM* zn0?S<8Lj4&3_?1MyznE%DIUB5Bkc>rk}pNn-z+=CzirFf`B0%T7~D08f9*ei>7Uo~ zI>2x(SRu;@-RO4O;0Ow1Wjqo5ww++CR%De-cb33PLgHrczWx#V0p3Wnc-vLUPHQ+S zx?g^>Do%;-&ObWUmpuBJH3y_8ue;@fnzOw6UA%*|e8Q@k6KWMD3Oud2yKZ2VWIP2; zKsf`x3>0B!JOg$6cHx>7?iLIzjr-Fcq5Dm0!G{q#5XqzAHoY54>y|Ilg(s%hktS;@ zQ;z5SQMrDFGkM+P5%OWGmHJ!n3RaX-V(d!ia^=NaX@jNrVmFf%TRe3W-x|)9=J>Yf zn7tO4ET`2W?XUGuCZGS*by2j#3e`Gi&@YwZ7eE7UUx+rJecLID8E>AEPp>svM8Z7g z;|k*QL-Ajksj1lYK~%pkUIK3StJ}vPMA_kV*MPStWRgyYjGa}vWCK0uG#o%KYAp}A%!tU2Ocg5H-Q5?s$% z*WB$-@R##-je*q(suto8j1o;=V*kNQw#zlekYM5L1h2OLJ%2jjCMp3MN=Obc^B=$aTc z#+T#=1?72n-Y-_bkC}-K%3eI?KA7g zQ&)vyoFTA!nbKBQNVTp4=FA%v3ZL~1As?4A^bPbT()kJ*JCBG5cL|`7Lkt!E3J*nx= ztQ!nK1TRtPjI~b9bI2~C$^3pZx3t+VfS+F_3iS8&D?4oOMETpr~@!gnXnArjS z;~lNadkGIIP5GQTZlkaZy22jpgS`#k9#QXM$`Wc#Mg(Sx44Ux$S}g)?VOMGcEZW5G zOm=~Rpg4oJJM{%dPp=v-b-mBEka&Ukb>EXI%*KZ^9)z+t5)TvA8+@%8oL}-AZS@!S zo|l}e68kQ65Hj&qx&C$#o9X7Er%bndzWtl!S*1MxgCO-z-E7pBEC!t7rF-z0YUl4| zU$cokU{&O;E#eOZaG57YdqH;V{AM4BcE#f!?QKQ($;2$(DznPa`@6`yzblDziLAx4 zkZEK*rp>L&F%wOAKXvQ^gM?PyCK*AGN=JgzJ~|w2OWS2KVbdHySp&B+e9L{n=q@4U~n`zl7rP9m3{IANpasBX>^0;B5?5FkQFf1 zE%bW zVjO(#_GP8s(t1;Q!`AEBpzFSf43~yHZ(1bG?J)Ss*A1Axe^xCc&lHWaKqn`?&A)Ca zoIfy5tZxw;4BNP?^=EjCfm&>6l&CJ!O3};THeA#-!}6WEEET@KJnr(qp@M~Rk*w8@ zTy#FlTK3xa$)zA2QL7ab*MoYgK)79igCwAikK?|d^bQV=R8C0u0{T)sNAr&f=Daza zgCPSuD(&1K?iy!3TaX(u;g%o!2*a$KG+o(4ILC7wu{+gmN%R54-O&64xHiGsX8lZA z@FKhLL{)nAeV}V}1*+&ILN*G{vF)WU3^t{_ghu;RQDn&lWi-tmjs`7Nt7JPXX3VFY= zq31X2BYau?Rc374>_m{m&ZTm&O<7b#5d$?6@sGcDLKIYdu-0$m;BN|Lx0WQG;d&L1 zK=qCV@_%)!POVQ*=cM)JE$}zZX*-u@p4$kmtk&OJ)x)Zn4JL^XStZYbpU$uga~Vq_ z(FvSCSEn^xtA-!>)0*C}FbQzMykd{LpMTiJNH$#}C9b3)$ad#A zi#Hd~8lw1tgxGI3ah$-20#a?dMtF+rcR$pNCr%B3ZJYekx=wP4b4yT!^JdM+&@kD^ zXjlirA#*D-^D=pmPjz#o-qvZwHP=vC8mqP=ujE|2C_b=iluUGaEHmeudc_sC`=Xf>IIHcfN#JVyuT&Vg0WqL$+`URxJ;4vrh>SH$D zG)`CbC2z_jKxlG0rvyS2vCjd=kBAt#$dcDP=afV|NE4?>Oa`I%rTEUmS~(h8I#0K2 z6aM3h^E2>}t2B-b{(ROh)c2;P79?~s?$2&H}5j_%>3 zg$3iaMXy1q?1;B_e}4jKyogPM)k(hFJhgdLg(U=7?V4eOjIA&z#8U8l;bLnukA3#) zq^R$)M6PCP$Q zAP#wArZ{shfhJ-+Xzsf4$-=;BqYp37z#eV$EwXB`@e`t(nah*>_yqgwm}#^K;}@P= zUO*kLNfTsiA?hrbUhbaHev`4K5_a6lOLBQ>_CyPDtGB z(Q=yZa1(%Sg%O4X^rQ?s6YBJR#0~QFz{pyJnskR1tM{+e=Ythf+S&)o7PaD>9)Y=# z$2i{km5x!MtQyx*xD=SA6Yr&Yr5nP-{><98{bt#Gu>I!HtO|S%>=&E%p}stt8!tHW zI{*7Y-hJ4>ZRE=IX7x3x{OMjOS5lxN$Spq*z6c*@4=K;zNOdO{De}j%$xisk&BCXw zIzOhOt-HlLrm7laW-4St`N`AnUe)eSUt`6+Y?*_)!=mz)TbDoR!us3{P?&_ZQC$f4 zvz4dxIo+Rb+!X0EA>$knnrEuEq4)uaY%-e_gJ}-jTY8JlD8(fwqph#g%LR^CM3sD4 z%ib948I@Nau# zhi7{Z?YXXd=+v%1<;2NVn`htEH=aVR#d^bKs{iQYXglNL04ESvoc=(^p+vM*?=55T zi%FR3UOOn?&hLDNy##9vM$23N3BdM)?B<~X_ z>%k)re=A5KtTnP2yfJloQMAhxc^2zFTT~i#v{hlypHbyVyJV#?x-66~`X~sXAC%uh ze5X>KsJ4;fwG)1FMkylnX#4WwCS(PVD_nA!Ta*ipuj)LdnSOr%H|nf{wY~3EQ}Fb# z-;Yuy^_|hTOb2GT0B&-Pgy=BLz;hlDNw7bJM3UX&(?-JLNxmCIRSemG*{Yj zSlnb}FC+)JY1}OVt26~hqo&}(K06di<$~3nzR3vmyoClrC4w}e?^($A6Tr7O5c=FH zsIhth5wlnM>>wNc#NGONKTVi`eWgX{=0(o3Mqq7epjW~h^;zs!n&oyo z>1V_lTVqe_SeZ`^td#BitJp%(8@PXQKmuS@w(eLnHZxSdxKmE zPJc8KM&~=fL44ekh9L!E{`cLm+wpswjYRnqPK82s0Xl9bv%24v*r2v5k39SK6_Q$&nHj& z`Ze!yiTA&v?%d{T-(zTX@y9T3{Nt8CUdgYl+kt->UfxW1*mQ8C(^_~77IH|ZNsCR> zJg!(9BxfFYgzv-huGkVM9%&9MM@&1!=fHHrM&8~}Ed=iSWb**`u&ku|hnP*J?P^<@ z4{1#7J;0r_3x&+%+< zoCla{926f8rA%eL;sH@oqJ##dK7X9D@Kg7{KsrU0%e+^l;>qey<53+`mNYWv#ZrSRPHP1sfZc058v`pc48e{Vu|Ks(kg{p^sj z=H<6cYWYVjQJ?T=G59=&G(vp$-6);)GN156um75!vM%W|SX}p03S@646n8<2h zj!Ti2)U+bVY3Ops*mK=99;+vSi#tL6`RW2`W^G1mj$Q1pdAsYD_`+}T^RMMtQ>J1G z5mrmY6FC&rGt|!!dL=Wznk-!2_}}S*8vN;B@7rRzjk^VCXsij+ zNMoDh&+vYnx4K@ zmfDL~4+vL?Bds}lEQN}Dh(UHM$%x8`?f)eeqXi&EoP%~7H%YXh_VoQ0YVnu>24y!^ zM=?PUYr3@6#0SQs`kC3+SKD&a?<;(C-V|szuv}){RHvk;r5o}K2HXV%Cc?=5R}a_R zU|TD`uomu)`+*PH#K;T(YvYlPO5+t%WA{ucW?AzPpmA@js7#iFzpUWkRIhlwZEyTt zsRDQxhP6+zx3-yazcDFj$i(tM0Myej)YdU3pGnboS0z>6aecliteG+z2hkDGJuk2* zhd(;E4uQlV#3j|&Up*QIeLc`1QuevWVfJ6)-&6LHh`z;-BVM9N>{7Jp@|S&J$kC(t z?3Jf@32SUmxoV$EEh@cNC2iar_>90Vc&`kBJ})h6VwSqutGw-MbZ$MbrH8muu}q|# z^w(Po($pc|_^@<{=XA;kBaAqTO-5ug_HBxe={3_`T zb3crpAwDrIyKl+f+;Q#;?RV7O1roFREHy#L7DI2ApwNTh+`B;fle%|nxy-tDhA7~) z5`)4o@mv)8pfqAD0@-@Y=Tr_Yd7XqfGnZy*?m%fED(LT1T9^$!Vg3T9oU3H3U7_2z zubM7(nsB!|!f~)aj_3-hQ4tJvKb}4sePNupOI$4Y^aUVn2{Ov-8MO<)R~O zRuCennHTPg#D5y^Deb#|t_?9`m(ZY(W-%1iJMlOE3XbUV%P{n*_h+wFZsv&n4I=n* z)7-!J<hRz|*1SA!CI_4r{=MzpVXl+3l?y(94m0US z7q$1`nRl_p{{04;t*=K_G#IW1KgZZ}jUId5WqAG+Hyk;2hcmT`IUG1>gNCPJ)Kg6) z^ub_bUf1f1fRZ!8Z5OOWS^w~BVz8^GSmZ64b)+`;Iw9BBotzi`H@Baz94?8@VpFz9 zoZ&)3KFTVJP|7U(9>WwG+DW&35qqOb3_TWxHr!rQNt;;}(dA(z++MNv!3 zd315zZ~c=-%4&N$DY&vnXzALP^5ul4bElkjM{dwZVkN+nEoGc~im8>OeqFQ*EtiLF z6kuKb$Kb^%&^Xln_HdJmqKb8gJF?SV-*e`kLdxO949sEO@C2j%l&G1RH`H0xb;K!@ z#v*e~dM`~yJwnQa{jvrX-Vvrzbxd!MB{PVwVM$Gq(f@t->9)TPB~iglS8#5pug?x| zvrEr!xa=^aE=+g3N&48KOio-;ex)Y+j0nhO6T*H*!6h#RHFx>a_?oIdY9jvgwASv0 zG<7{fPevkz)3EiloM8$>c{f-=db)6J$CmZ*e5o;$jXB^NqVC_OFK}^s5EP9FqU_zF zx(nqoN2tKoj}TyVXPCX4 z7(?kUFTFLZW?#MgPQ2%@0Jf;m&q*wKHUG%~k|6Eh@N9PPH(mi7gZD#&heN*X@#uyw z=e?sdcbg)K!$ONiN47&tGhI2))1RQRj`OU`LDYPSYo?)*DhS?<~?q`oa>4Y4NuJMQ7sGRvV^y6wDwey5p z+wKJ3pPNbaNiP?&;~0T9fg`?%wRXY9a)Wo!pUinR`-#!sBE$G`k}Zp=?ay0RK|bHt z2h9ZzaSMcIMAd2OT!+-OtM#+=-*|@U>Awg8fjjXgg$$l5dkK!W zKLQye(>0AjGnTjX7_PatAwAC=&~gfNimZ+3dPZ12 zQXU|DK9(GGphVEJJOsvD*%~QB2y{FTsAG%mW*Ptr98QHsS)TC%b>6*x+^PLNnE$pb zJ8I7lLiNg99^N+vN(tCfw3i*xb~yhBMjxx2Z-sncr*La0|IL~~ls^<3Ir{&G{wi_1I3+}ZtI6(e2(XsDLu1Yr-P3m(4vZ!qwN#}qsmD4T}3H<(+H|d zi)Z`IX)om`EYzA(goMp3W{%f%_Z{v(GNl{sIdn81-hA~f0EJ}@=?VI?Z-XEdy9vjwDKcY5E|N(Q zmeuyjTwl*SZbO&E>K0=;gBBffsNTkPdy2bmL~n-qV4Z2?e7|RUJ@VadSD4J$)>)r! zMeZ0A(^7}H9%V`pJEbvo9R|IY1QAN)`9#Zs)P8jev*6hqsDJ8IDBpJEmhjwI+j_g- zqCinV(jVwu@ZnL1`73P1un(BpyM^hY!dUzO+T9Yh|7Ee2<@ z9e!=5xyZY)R3Y);4ou)$!w$YYITaU^2QO$Be{>J8G$ae&r^)S66^=|ZH1?}=9?P+U zvl{v5sH?9-X8kS7jtPLVv{b>TL(HBu*Zp`a(UI;!N1*tvtjYebtdBZ?W2IgrWG(0L z#?+5YG}p`F$d1q^=(F)0WeK|tIq{afY?AFK`ojD(BnjWu(kt71o}a41cG;bgDrP%{ z#xvl@(?h{}*`uF{9y5yt(XX;5&%4If8i=GYHn1ejp=5iZV>iE(AyF0BJB+g27*q}Y zUp4gk4%Bg{OE|1aH zUJn47qj*DZxmpK+uiy~|g+BU{qVeIVOX0+)*4$yHQFS9v!)`M$-4zEDO7O1oW6=16 zuN`dhe7R&6(Jj&){eWMsL z8mGA3hMk@Y`A1&wQ%wj`{4}(tf4;Vwq=*qKHZ=PY=s)X#ew2IFKi9<@pUo*d0y2;S zfd@?v+M1d?)zRW=*|flNf$py0=Mr1g`*Pi{f-0w)&kKtdTw=2)Dd$_xDPJ!EUroPg zTWuci%v6w$Ka#<|W|t&@Ag@1{@w&ljvQ(ekZ$>K~6uKLp@zQpO?wWjSCp&P7{}9oK zi*n*ZVEYVtHzq%>J6W-p1*;kOV2s0p=8#rl2Gbe9VIJp=-Q|~?0=fLxVS59~zx5SbZALkja zgMz-|&_e*D7h72;l=I$RkYTRYLf}aINLFoj%s_4? zRH^6aNB5ad9PQI!8f)HyC~2Ip#!U@})IZwwvfM9fah)6zYWTj@CsgO!i@n=Ki-U-s zs$fo>TCsaI%Fta&&~V)DbIj6gen-QcUoIR42c>Q7!0qnbP0&1@Lk9)Rx_brogz%bu z8|Sc0USOv{@SWz0UtIQ-oRQq9Qb>?0;ECkyn`(rZ4=T0ocmp!0cl)Br& z0`zf)m9iLMzAf6{kH6rl4D24XN#{?2vT<4g)B#l-ZRA?S+u%V_DqkydjHMs8+ zm&vPULUOcYH=JYhT9p*4_+S1+Qr=bXXT0Cv2j@r&Z7yaJVH*BI>3m@PkY%VmUwry~ zVePuKaSuJ0<5-qp>B_!BR7UBx4UtjtQj@{4Q?}(?rjbK5;No;k`g-=s??tBBStLwx z!9q8U=rpcB5J7A`yJ%h2k{WeF!>?VBhhq-8e5x zx;sx6UHbldlBmp;qiT@qvU~Ay=t=qUw~*E{tfGdB0LVcar{#eXSBrJBaok2nV%LZ0 zqh?mOF5&`T+sehltq)SD5L;0$n5L5hyuWcZX?vy)fHsny&Ed+n>5qcg2KP-Dv3(Lr zzBQESxQp+8?O$k+aMP4ui`}#e8mT$vxB41P*uhtByFMlUyA8V8W$*=iF1z$8a_isv@ixJl_@7Yg=76b~f z6GAwCvK=0bKao(n!eT5*LDb3MMbU@*X13f0p0_V!Rm)e5;&a}t)oO@L=nFXB=Z+*E ztS(0Rkd$$+G^fcay^M%I3Jh45v5}joy~kJc=ZJ+0RJ=dj7N^hY9OU1JuVT)x4&8(B z&J#y10Y2ISE!$a|{*}JDj6a3jwHIQ1Ic}0nH@Vdg-d%{p8-IUf!k29%K`x>qX+x)A zZ$_xYup+)@`#ElL7VEe&>-hCknrg17b?(--Pj_{m@kih=`2D!`p);VuNDNQ&Xh=Ik zo5nnU6u4)4c;MTWWCM`ojIzFs}*GzAf~Le~lHvDlRRT#u~)C?tU50;bXS zMFG!vkLeW`7DsFWDn1=_HupGRgE?(H<#8zcG=sv)=L7o00TUE}LhKn&0EP-@q5UHeq>5DY;r+93vLDF%KeJC+=N7ta3xN^O{%9Mw z3U+Loot-MqDoiSPRQm2q#u2-FNkh@YW2rl)RsD=<1~EjT(vR)+@A4l;XHGLIjf@>9 zg*AB6Mhm{|DjRZ1CmSzXOr|8%%u!5a6D5o8-vFdQn7V9I#yngAK;XShC7uqAN~>p6 zfsvr9<~w7xTs;c>b$nxyv_?ht=xeRL!5{?oY&CyUUQu!7S`7M8QQPUm(rXcKvSGHA zQJ$dADDFaF+hXdh&J_P190d-fp7D(P%y<513l#u>s)g{1DakA24rn38g76AxJLStp z=n|8lU#EN2m4Rrh%zW}L{PRiS-95PnEqra!UoxB|^+?}+$G#8b;C>F5n)H{9y;?+! zu*>}KI)nAUIs@{IZ~r-?QWdWOD1B|4H>a+ErW>cj`>CUcMKZNu^7&!5bgV$tL}?WY zu9OarkPmLF#+{{z8mQZ4B zl;P{hCDZ1oL7kGufK+<*^&*lXIshO6`_aT^(%ON0xf$xqeoXs>W+`&Bdn2LmyF}SE ztTEH+4G}Llu7yRGJ)s}L92Q*we3o^h0B*L&$=DY00)`DDYOE>;cpd6W4claa3|qE0Z13qz9-okkXT@4Lcu z%o}sxt_(!4?>jZFc1U8I*Z8>n`R}`%c(5&0h4pQOwO=D#QuS?rysWWu8qeK6(Il5c z2AL&$)oyXXr^8eJ%V{vIMuI^LV7QWy_XDjiw{VH+MqovwTlBW<*=%8 z14eJ?j|7(C%?>s5 z>#tA7zKC&V6p9?gXI&-E_Z}Il0_*x4f$4`XC^X+ET|Ru}*!<+Vc;Mlk+J231IxvGd zS2qbA1W;O|4ph6u7gF3*ww;M{%i}Q7Xpm$`ss9>y|B`<8t=>`u^xT^)%=-73xaC^5 zz1;p_Bu)KSTC7M+f;Bu3XTpp9Z~GH}lYdo{BrE0wRonK96x!1=&Jrn{DvmFw@t4N> z^FEXv+!5AczL$0BFDFAYmF8|1lOshLNka2mVp~$y&d9DaI^D~;?|rLUZApgmxqW9^ z+ba!V3V3|C!JqeSMXE4k$1gG$$QWo2A%g=!lrrcea?rG7MaEv+OL4=~yUuHZDx2oZ z^9~=YyU~BipXSY1<2|@ky?J}WqAtbdq(eGede#Sfq0gr_1=cP58le{)V?SbW+h^Zv zvfiF zY<;WUyw$dpn=UBBs!n%qpJYQjmt4ReN$q)dZ&By^DkN$Db!t(fnDb+{rt%H?Lr2eS zBk1KxY9Li^yx2b&4_?fj9c>cx?1m9EG|t>#WPvnt-8%ETXsW?N(H|Dz1n#I7E!kve z^}WH|hAb$8@|`-=%||B}4X-D9+bXY^WFKLAq$ z_}s}Wr_(+=$Xq2u;IK<#%$LJnDEy%kbyQ&;w?7ymr*|8Gki`JlzH!Z0X9*pcmGA4+s~}|^ zv9J(J2ikw!~5_HMy2sc!ZxDC}}$c?$9 zn#~J5t+!4T;wom?943+44gTVOS2KUmv*lwqu;Tzu*An63uir&CA$E>7t=a@)d!X7< zhXVIcl}iqibM>t{!opXJMtkWvqMpFYyTB@|G4;M3^0A$#Zb+5PpQhWxEjsnl4uEP@ zrPVu6_7a9LR@_!JK)K;DbR@N?A?>8wiIw+Uc9Wn zIcNN&s7%eDL>g`UW+jkH@#afmP%DMA48?Isk3N~#dTO4Ip3qg;Ql;}T24=dV?TXbL z#d`V6#Od@W$>AvsY@{=u-VF>;23Nj9AAvMiPpJ2H)Tl+Aof!ro4%ZT|jcZD#LG}T! z$iGEC#$ut2WMNvpTz@*hk4VUEtF=k3*I!zHhW=$q+c=j)`N^A*2g?h+Xe>Sxr7J4w zDg{A{HNi#>9X;j8bkBWw-;~u@%Y7>zPJ{O!9#3nLL;ZeDrVT3lH@+XGLzeZ+`Y_hSl=Ub z>yj_{QB{xDWf11FOauUwJRYcaa(X?+%XA8ni~C8e;+AYh0Bw@R`-mWJ3VT{Id5(V= z79~pg<;B*%ZR?(KxRUfu__yydQRw0kc#eeXq_fJ2xM)9;G~)-24mFnTo&Fo|3K<3B z6u~<^j*eEpkf74brpQ#I&6dWChE>vXAa_I*R5OwPe z>^geYHNI<+P|OUQcRCRoBIsb%!Ik4a_ZPUAQN_2G^2|koZBUz9+_l@Li zr6Ty!2Uki~tNN~MyhHGAwg<53b{Dd?7Uwf3^cTlU+5g3{zW>FsnW+h|^-f=k2&7br zKjSH3uC@M3?24iJcA!8!Dmts5S9l9m@O2|CKRnB*cWdG)Xt;1*Hj265^Rs_()v5mj zy3>n*>h`jqCTpmdD+OV)^wwD2q^DC45aZh}iKJkCjT2-8OFI8b<2JnZQd4u2r|ir9 zbxgAwPx!iP+KnZbE*Aw#Q4)XoTPBlzki87Hw#yhZ1m@o~p%m+Ox*E4VhqMs3m%=iu z?9x>kqoRG|GfSjn=U|UHPmWJ-ikVTEoXSBb4Hy{D8wfE_Mq?&&#KGw$cstJ(z{j7xkwKsV2jFz~nJnv!r z>1bZ+$4@nhZFG%b+jIi>D$fNR81o6DV+8sQ+nR;c&)dT}RMtpc;B2iO5&i=*EEWcg zico#hUt&AW*_IMJM4g`5h$TTMssm8~V}da+QPfQvuP@j0f#{~?R_U^I{ZqDQcN7%z z1_wy@ZD02R<-~jO`!b)&Q046%z_05kd+t`WEzdPu*eieSyR=DLu5hWlp~EJd^(o6z z3EYfva)$*0FD4{|&g`+Fj}86BpgGYF$9VSPQ0RXk6tRxgtzkyv2*P0$XQzX5(g+4< zKuQjbSvtaJDd?f8ss?zZxu^@x{EO|i(|F@v`g2{shGQY7BihE)SRY*(2-VlOsNjgT zFqB~@gZ;iMs4iaOORkMhSyUccr4U)W`Y7J z{N3vRxPoe|aiRc#f(f45qk(?VIjU8l208+@`#caKo+$|f0J^(Xr~!b1PozP{W`UxN zL*vD5iMiqcnhh3w0M@7f;35E^iK!im@(&s+)4iwq1cs#l(|7Z527KQuH>Rmm< z?KTaq>!g~N_w8)8)TT$KP-kDrj9-wo&MZv_e97^ThjEVY5z>REpP8K=PvkXN+Ihe& zrT&alnH~$S6s9bGj}|;#f6GK!<2M6(#*zVY?_tHqXy|Y{i|^>5pcVNz4HyF;^(~W5 zXqktGuG7oCwbkTH;%pu2Gp*V6@Lqw{W_5}0)I5c*=cKc<%kepP?mG9z`a*_2y0NY; zcqGu#E3>8A^k`ksGhm_-gZg^jUj!;`%y>D8cEk$ElOLkYqCo2=H`L!ADg99P|K>yM zE&rc=XrB($EPl-vWg=!nu0{mkvoYETo6)y?ORn-D2GZhVM%)4@?zXsV&K_h2ipI42YRViKGqUf|GPQsn=CKNJy$BGiIhEysROiq-8!U%i@VrH>7LLJqutv|*1+T^ z2cX`3Ri}4cji)4#Nt>yLJhJ0U+3WJF(ZR(6`GY2=(U8$oto7Z%=2-oV7&h?kxq7~> zd_hfzu`1|SM=2}C+Uc;NnDs8R&(;0i(C*9gLXzkG{Nl?#k`*6sL3Pl`=Ol&3K&GXF z=(=2c2%HwK7H8ulOldhUyao3f$ZQXR|9I86bDz9rM>-^wsZM1lCZKkc;j!N&uj;}wrnB2dC#sVnG zT`ik^wmE@9iv?j+FOnUQPVryZN4bJ{u{IlH^oRQ-TDYj8f4DD*fCNE_eJmfZs?pFS zFKQB6aQh-j$I{y4e*wR|@&6n69shp@zq%7<5hw3gtiljM<|!KBnYxb^3GIi+3nQR% zr0Z@vbI>*@r4cK3?Tsht|7q$Vc!J9EF)x!EZc)j&&r^IR5a-GoWQJegewlv=`006^ z??fS5qJL54!N=W}bdKMergKSS0cmC+)F!zlS8)w)Rrm#F?V%O@aq1{+>P8MBl+LV z-MasnyH!KG=LP1VlXc%&m2^oK&|=;k!~^0gpSyKQ7+PAi*G?}ZwCrhSeeY16!a#$W zt4a7ZdV-%bQSvDmsjFUd_U{pzDfCyyZc{^XEy)e7>_dazZeg1o8Iir zc2+#1_T+FsDcDxeE|MaG#u$x<3CrB;&nirf`y%)TL{g)oLz-J#c|s2Xf}GaU?X@dk zobSZDWORHhN?ZxT`sy1qoSwV9T10^WiLsc3+SC)k2}tF`Xiwc5ZQ!SzV7lry=?YGd z5E*bM+a$K(zi#Xr0k>rGjV`Ym`wI2}A9l0wX~(xhgB_?d)M_>@cwc1~t%TdZmCvCn zT_>&_Q7hdfsIr!F&T+-@D%oq|>0`9;dq*#-Ax?=3YsW<_;D>MS9S~iv3s(jS^>yGt zNhi%n+WDhtE3+q;*aemCIIW&C=0B@0a>(<5+P%y$4YUK$lj!KjeBpQjhM zW)!WXap&d;(2kfm&}D!^#i!lGyv7qg{NcC!nu<^a!t|}fBzZ?l-{1^xs>TM6ch4UW zRXgPvQbQwsai4RTKegtZWnNW|?$?8a4>bFQZRA+pD*y0%%5oc<6QBkx~C z_M89zL}X1=v&>FNB8&5lvyJ!FTXBfZBxHj1A9^QJVOkA1`Qb~Vnt#9>{6#=M@Yr)s z;_}T60WiK}?W!W~GRZhYsq^UBBSqnEaQHNWai2IdypN=i|{IqlBb5`)%z@gy)39RGPrx6*s;|cN(SGC;%3` z7QS|{^#u==wXgkjkcAMjxubG-RPW_t6p0;o!eL#8;nMppD%*$A!xkzci;bAy{Gmqi zjzjGMHoD`@>5L+8&vTn9ISZo%(sYf-#JN>0gT^W7Grh;Qts@&&q#n;)_RL-qQ(Yr? z29Aigvx4`au>@nJtFdT22nF*6H}By&$)!S?r*LVXz^vift9K%7`pv&KRk?ncUd-k9 z>bGn$qYYR>)>Qp@n<0>)I(&J!pI8$;*@mg3Gkg?AG;2nRq1c<7NX6@IiL78Bii-^0TgdbWo4J&hU{OwYk(pta4$<$i zqHlna>937LxW1XN+z0C3o71E25-M>VtUreAsw#)0EO{q~A+&gq(~F?``dyR;X#V%p zxo(Ic7u*yntr85aM$~+5^Ab2QD2;?%p<=J;-*5PtaWH(*W`LG??wQ69vZC^!wx1(t zsz9adWmHd_Hh*;Ai1gkF*iT!^X$|=k-FR^iS~|tSdfCgSat`~6z!yfAqiIyw{w6+`KXY8S6f|RA?ZQ%j~~= z?_9}sa}gxH+{fCgAlJzHcscsyQp?uYGBs5~5yQ}w7~ap?mHM$8>R3&WUA~`PaofIo z=uHr=GdCGvodD5L7VTLWUL{!Gtyc*{I8xpqXMvtm_9}6&%aeWAr4Nlh$t+G0%|4{7 zMzRv-OmR0~hkzWT;z!c2B`Ss%kQqQ0Xp$*D0~^;R{n16aq{!xLYu`-mJUqQ+_q4yD z2y4A)S1wnonTdKMbs#|+QRNUXUa9(h+JG1=z<0wSqg(0tk1ywd_Vn~leY`cMw-ZKt zS{D)vNbo5^y1qqlg_VOb2xk8LgIplc&d||j@iIAjDrl|N<&5H8mcjA3)lB+((65+z z_fj);;zfe1CY6`L{1eG=C$Cd;ZhwVAf+#iZz z#ID2(9{y3j5Us+<$)lCS4NxX5KAy(jCIA44ksewPJuvycz{H%U;oDx)U= zVDg7@0OnE=-2%Mbt3(#oGpm*w3>aw0!&15ayA{?w!t*!o00K+U*pcbqzqdjH%KxGL z41O`9vFVZ3XQknunLjaB9m~q5gNM72c%EE>^oqm&b;thk%Ona+lS|>6?*67RFUUZO z{F!`zLs-sxKlVO*^?K;qD$A=<#9L#l5|`lVb6>;!R@ELY8kJ)wWFFQIOW?)Tv7l<= zrO;j0yEQs&*itKfqlr!tFr#?9}#0a=_yc!?jLLX zp6u`IW0Vk%{)HSl7lbqOiqUtAhO@{yMK)%gPTsHX^`PpuaesvXmkpX(iU8Mok*UuJ zYFrrN3B>AW_GjkOPeXj!wxJ^ko6EXt)=R0J*7Dm5`_aBT`OcWaTo*GdVAJomf@01+0+nGnA z*ZTKmBFjYKfG1u~XTzVH{J2&LgfnBIziuu|=u+fXwuX@GvlA5Iq*ku5D^?V?Y2>m; zsp>oR;DJ_JO;1VNx6Z%f&tzD}F0ZCr zK`@_^L^KrYF&SE&{RZ-m?CPMjIUD>q?@ws-+cW3_qYG3RI}cIGQ)nQaTB3dgh5s-y z5V$Vm#+CNrZEw=0Y;JfY!a7whgI(_*Um5QE`|MGIi-=2=n~whE9{Q>OuU(Q5aq`f2 z_y3G?^Pb;2q3NQqeO;4h9Q`A|x0n&0sO!(kFLm+T-?qX7_1aVFMAV|6nJ%1Udl>av z7*lCkDD76@vD0cKd&=m#w(6ef&qJJs?`FQ=Eze!M#XcskeSDd)ZY}gPd~1pFxPzgn ztwr)&d1b3cVQXY8pz6o2mbWiBrE$dZ)b(9QcarJy?Pn@~9AAWh9bN(NH8k5=k3rE}p27ZRncY6MO#LL_2D-LOoIO7~);-TKmB|J;bGm+Mu4sQYqs z>v$FW(u8&v@tVh7Z|Og?&SxI#0Un0Qd>zJVDvHC_Qtd?ch62|MM-i~CaToqXhgwSh z_k=?((Nl{dV~?F2A5Gny51#t&+?!<19Rz)q1AjaL<_xYS!-bCZ$h)_AJuBD$SpHFB z%w~AFON28K?~lA%O|)(<_f{P`M4E(Npp;7*dx4!T02N+V=M;3v6rIFB<6+y%^7IJrZ zCe^Fh+@+5<_wT{@%$9g=Jl|QTYBTft!nQw?9!?y+Y6wWRQwq1Wzo1nNC^!521tpXoGKBw+6_ofMo_zj3$3**Xl~4d~u4=dnjBRnc(= ztwV{)#B`#+Mm0T*kPH6#%_u$djMM!G{Nt;N(v^VnaSB+I7p?Oo`NLd{k-~ztW7cFY}qQr+i>T{}1r~h9Qz2&%JX2C!-(p7h2%r{*6Ezj(T)fbj`a+)=k1x)$A z{?&T@+m^)`|Nfb=v|}S2LY|pO_2s?|A6AEv#f&>_`D1YRoc{9<3q@oQ9&y>ej`Of8 z9$;(1@Ktncm<`ohhqA*>t4wA{jk5ESDcbTLMwk1{Kly1(7`!bzW?`FKg<7_n{yIE` z?C+k>5t4JXTnHF@tKELrM<&v^UBO5|5uZJ(V`J_s*uP(ZEVHoe0ng{m{^Z;bVNmz` zD58(-`IjMSA2oLs1Cp_ruO@fMMBJ`X_TaybmYU8x&aH!5<(Cv==~_E%VF&8gH>%n0 zAOG!P%+CLkA5BCkkyiOX0}x9o5=ntO<@8sGMv>j?ay?y zsn}`33p4<5Pj@RAU`r=~@)0Z||CA&$r9AQ0AM+tp0DdzSL+{Z{ma^C9ZxGDYm_%;fgV)w^G zTm9sUMhXkIUKNz(so#)As z=fd}Tw&`{RB{n>$n+ir`p=u^GHzWAcPJ@joUf+?@CHAvMtu$a{>gpE}1dw8!D6St$ zg1i-Dur(e~0EvMwL#-`#f5r9DNgX+ZqipUTg8`_Ir7y)-J2^zg>+t`myA&vZyhl}t zFH+^Sha%@TXE+rRBBOBa&bi8ofs4v3C8XBs3$;g#oRqWaG|{rVms`Jc7*fu-&6$_g z$P{LKNRe~YY2SlQkl5mr(4|hY=fWf1RrPxH&$;#`04Atd<#-YYhYyn8|{(#%v}M z_QiGh&BZQWf)RngRmqx=?D5PkWD&Q@zq!`=jP7Yoxt~R1cKqk5v_`f>q$b-5QhBY` zcs$`S_7*M34vc{2P8$EIZMh`a_c@5aDlPT}H_{LFe5CydSIZ|60Zkc$A03wDiIYz^ zZrhcW@3+|=zz5&Ecg$tqE+ktEdtKw!M~9L^qAywjIrIIdBhvLAG-er-R=TID>M2L} z;r9;gO_uT@?dxLd*!z)Z8T6-43(m{(P|kpb?*{tX4_H}_Q8 zJN~rj9OB(l1*fGrlmqzf51239+?B=3nz}xOtxfaaAd^ltj*gYM-n+rCX_C&td#0?I zvo+bG-&Rn_5Ys^u-T)UhVvUk>t%eIw`1m-&}Jsu$wUyY+1B zn}1#t<9qEPiP8%YhkXtkjWG1@J>lQ|~JN~}%VBD^0n?@l9yO^W$XpTZ_7 z?$Tus;LY_Uli=rB?q&!wzyL*ddc95aXWn`LeYd1Jn0#ghx+mp)j>onUom2L>2ryxi zEf-Hu?q!r%@Icvwbq6Cpa30F|^9rvEQJWTj)RB$tuc6=mn4vzuF+a+|$n@3TwXWq7 z4)Rs>Xb~!YudpKf_+UpsEzDBw3H`Ng57&FDEKRfLVRl=e^t0%UTW3|AV#&ZErw!fq z_BY9%geOZAHxY<ZAE0$Ek2w0x)_=v&O6Spf}9$AL+Q?wNY?@0RN;;iYlMB%RE5#B#hlAKHK z!PVmn2>Z!EF2i20>!=bK+}fWA`1FlC@cpHAxX|3gwby!B$hn=~<_3bG> zV(jUNS%ryrOdLlBVVHuaJ?>Ri)m@TQg~x8w>aMHf8M7=7323$#1EVDGcit{fS9 z_fqQEf^X@-Z21G!1Ha4M)n{p^qZ6V;E#&x?j?YA=5X$+_Fj9md|e=?FY2;o*M>7B*t+bJH8`8Cv^p9UF}Q za+>TiK}%-0U=5OsbuCNCcboVeu&}k?Zu3Bm4a-KcKgdpZj9g>yLCV z=p9Pt&9$-;*Q)?LYv+}CxL?cam(G5*JisRXZA6AMk4iZvUU@P;_Vd08@b#`)U;Zs? zsCi{Ym>COsi2oudFF@#m_9+!4=2zbPOqhfk$IJ9$LT0S+RGgUlB%I?vFk|ZHO=#a%$UB%I7_#3Pf{#_^H_5BZk%PcEM!5Zf5;+5M_OA(~O_T z{CQs3e(2nu-+P-py~cuS)H&gZ4t0YnOX&s8d$SSO~P3 z4!%%Y%y@l%&V^HHDQfeO@rWrJvkvp+%M%?eT2Ac>Jou`o4O@%xbBsAUV_}v@$5OsP zublY{%1fK2f-uh9flrI%g{Z<6`yK6mIA8QOv=UL@5PI60b7pYYSvRK`_!zo+=OQ12 z(<`#l@i;Nv;ogRkRZOBbi6#Xx!K3^)FqqqmAMcd6FsAq_r

(UQXmyv-TMg7DKm)=v4v>dBv(-8-gax%FsN_a80gfBr*5#Mc=dzPU9n|*ka>Dg_Ow^_*H9;R znuD>jS>+$o0GIO`+kA+6Yww?lTO&ng z11)x5$S+a1&Y?Ri54Vr)!q0OEpIx$}^#rV_3E^-p9V7%9Sr<6*@ZgR$mtg95aJ7g{ zBA>RFZT`@^8(Ru}cYfN(IU?-T-P85G^0ZK;mfx69nyFXxd!=Z!9aH&`p9^TM2ugK9bib-c))NCLA4`8_NM#yh{Imnj5HphXS9f+!K?iOz zyJ%Av`NmohWgoE4?8_d%NVUAf6)SRiMQWUK1G_R(bxwN9IvaYmYMIpJ46MQ!>HjW& zOaak`E~~YWcN`U_B-|tgZRpd%sK#RFg6D==%r$cd38R0O6eOccRS)a)5*>rlr1DaSTW0;3-lJ&~7ysK;r% z(UP>e8XlJnzU#X=%yx6UN3T%8_QN=In4YQ~gTl?=ET(K1Wa&F>F}{b7jo@Z?>;)!^ zEcHjteLu?uM-!Wzixd+MJl48^vLr zR09Th8vZ5`8_e3bQf~~Jxv+qdROrsX^P(Nrn&$Mw65!Ldbfn;tDJU2fzPfoJ)#Nb< z>YN}Mx&3zg2tQOTb!*oi`7~2u-Ov7Nf-2;o$od+RP8@71xW>X7lWmihd~COi2dhDX7b*H3mV;Mbz$D|)Hw)ir^w@YUhw#9*K&yry7>q+ zf6?_rA|QEA2Sy?mGV#J=frDJekdM(nnWS`534AgJ6GRk;T-7Czd_rbk0BqRx^CrYW zMreRg!l+-Q#f*>a2({uT$>c+qT)d&a3l%ZJvE@)^LNDVHlCc3)K)17$FFp$q^cBEF zp<6{HrWk;pxJmB-rJ?N)l*C0wU9={Qf)&wy@Bx&3JfT~^Y5Hil8Tk@^p?813i_OUO zw8JcUi~Uia_V8DK{tgW?RD=KT`LUw@Wmiqii~m+{Ve&t;?>zpGRAdfDy0+XCHF~oC zt{I#@&HmX-hS!sMf2C%KJm&V4-QL)&T2ciKR{_%@H*GrL1QEJ*R z{7Fb{Rli+TFzHCoT;k3x2H1H19^P`1u7=R`qO9WcL7JN3oG3 zbdf4k-g(sWhwtW>Au+N7UCepe_E9#$Dfn?S?2Z!$Vp_7IJA2WV`a%l!a1nO6=F($w zIhbDXczK0pn1nVtG+(W1fAo!f<`E`O2+CsLEXqXdmH9mmL`<@7>;LI{7 zT~RH(Eo5e*xtHmJU*2sh_wm#3y&~rAR<7;+7bG<36d@}R25BG1bXENOac&<(+oZP= zUj3COc?Ta{?KWhqSjxh}usT3hbaVN0DUXjTS9sU(GFgiqTEq`k2_Vo-M8EUh+pd`K zE_i(xbAC4Ljggl4_xa%NE}zo#9qA_zenx=8s+fa=I@7ZG&h`R#OM&&v2W>T@DBqXo zcmRrWyx_^AKh@hexWF&JX?mleS4$Q8Po#ygvFH{EEi7`gnhKsvO0I zmbtVb1-$N&bNXpm1J`-M@&=!Yr|EYRN-6% z`9RhCcT*5~q+6mFe9m(GNqx3mYQ9)#%D|3)ke2hM4OB*$llx=IBb8uRfjzya0T}JEQ^^XbFW*g>o39a49hmtF1gO2`;)O(H zqkOzb|Ev2>#eS*jUE9T6JhPz+tseDJLdbIIWaZ9WOscXJiX8>n7im8AVmcScmN1*O1pe= z7FP>wrar*uW22`M*pRI(<)6-Nas2Sr0UkvOKgZ*B2|Pd)L*=EQhPW@3b+S7P zxJanL_KnD|*L<;wiDG8D_u+Mz(-cX@)*;E*%cV!yg%z3oyLI>?kc?29Pv-A>iS}=H zHUpbHB?I30^MQzfdZcAAc+cpZ@)DQOr?MVi1V&7itv#6ME0IjXv3VeRd6cK%4fVsw zJXnvP$|=h(tA*xT-!7M8+swOMv0~vIZ9~# zwxip{tTiN_<67v^1L6KMD(^PfGwz%+*Mx$QMZy^NgLlR%{-UHP(r=eLT03SkW4lsE zPT3znozCPjFCkL4MUQ<8iPoOnAK=mrzuvBsjPboey7NA9Y5jfU9y*e#!%3lB=tg}o z4q^gXf@5$NJ56(^zZ+Y};9d^Kcf1?71zUenZDD%ja6-eDFm_vQ@ww*T=xvl ziejbV6RqiORH7?B4XA>mOZGiOz)347(i@+JN_2Qg zya~>rR~(c44QaoP%GPSL!UdjtYcM$~Pn=cHUd%@ECZ?siRsK3EiN`n1L+!iL6tntb z+Jhj^4^{<1^F=lEE&jFf#MzUfyCn_XU7R|Hec6p8rmEcc?^vn_>eFTPBJXeg5MoD> zUL@?iG#qjj<3cpwE#<{N6Vb@adOH8I{$&l{Rxsm|wg?O~~6Zc}n3PJ5GS& zy%a@X6gfNrQ#;qrmrw-FG(U=@%UY#oF53FW!yD<|KY(!(&L@aH|b z;s>ikv5xwk$9K)jj~36gnT}1qB^se;1M7kFVux|1B4!PzW|ET}J5q+O)gWm8@+<>hNl=U-aW)Px3Ky5e`-VPRl3JMNk?#@Swx# z^rlWc1Q*EM3_Qa$DtS(B&l^g4#lxZW%;SS=h_(<9bJfT*`$BayE-ssb=~1rwZN5bR z(E!dGCHf_m@17Z!7VcuU!U3LBS1*4NGGlvcYaC;RTA3l6q#IzZ>sihQ`+Z?1w%zzP z6oj5lNdtoh@Z1bq(ugYjmalP%mqhF7vZQWN>wfd+Qa$YP_ zc$qv%8VLMK_;HNeL}LJAt)j=DkI3vo9#psoe+|aRTCdKYF#}Ve_WZ6Rub$tq`*Y{Q z_p=BU^}br(?$trzD~KZ4w-+Tx^l-VJ74iQ0-lZt_M&=S9R0 zE&Vv6hfc$y35jt#5yyXda6yEf!Rcq7mx@txiw&bQD~Y{5wkOLto;=Ga!C>7(yibR| zR;wx3GCxg_9ycmqIGz6V6R2EVzPN7R4!Bx_h?cpm@!)>I1glQKOBgqvjs_siQ#qVO ziDhgtC zHBL8;uiXrJ4ATU@uTvH+P8X)9cEE>$Aijs#KkB!KY_y?TGZ)|4s@r?aKoJ_H^2@*0 zaA^#c$TRQyIjOhI-Cqwi)`&p93ESl8$LyAfNuV+MvDG*gl6pN zh5aX(!n$RH>Txx)gs?-c7B+FeDb9(uKB2r3;Vk2baJlmp)`TvdqVJykorCg`0w17Q0Vz0{9!)> zh|4t@i&5f_1gZy0z)Ot^o`KJz>{?xF;qyPF#_rqnZq1KBYOa4?#aYl<(6mq>r(+sz z^&t*Up{uz0R5M>D?{^ic+LeB1(*l|Wk7IFC z(SKrz%z+j1@E|q0{vRl<_YwLO2kB@P@480c-uvOwthbZihZyy`H6;l|oezCqZz29y z#TCx&_HM*OevmF%x2tiowOQi9aaJt3#b@HP8_E>%NNRaJN7gpp%B~c*Z-Z*Yj!aNf z1j0W5^aI%LxY$ZakLscErmvlBlpecG;20aah6z^vHj>Ct9`lzDZgI_{15|FKw~OeY z`puBxpIQ0dl}qlVou^>d%1SE)+2=BO6Ok&!#1syHX4Zz5P5SNFr#p-WuQPaY6uOH>dH3Y9+;s~y7FT*uZ zaeE2%@Wl3~X{5apx`eB~oo;e?T<6nt$ZkKMPxe@rSTkGJ=66ff|C}H3xbP6hRpgpv z&gFuy(4Z}&AztZ5TQtREo7{z^+=X4kyhry75EG#FH%_AS`5(sK#&Ln)c)qz#5pnik zs9G9{HI#469^xOzY2!#H8c)sTQfG6#TN78=b04eocK=DRZ+IX9xaaS;I7B^ORFIOY z{9AExAGwH+bI1o`vBghc-1JBBlwNs@P3aL#s4TifNj~^nakVR=apmp(ky;=DTth{( zbD9=?k_E^a$-PpjClrCV@qJ}h;fbHPvCUt~D_JJaZ>mkbfssY}0`4~OQXucU&LLLt zf9WonJw`P&MDz2AO3u)(7<<-d+(AE%Wj&z;!#HZsB90gHpL&u88)10bHgE1U=8!*+%Cee0dI2?Pef?G72}tgP z*Qst-=slMzzb$*e2H{=ELFs4d_+`T4djusBadZCJ)nXyXxtD$$J-*O+OGdW-K{IdN zT^w%snH{%8AO-j!3`GrCtV!1g##tYmO6u)}3=z&D$@L%=bYM$n_vN<{UQ;?Q4c}z- zJ~niBVtf~p9BN3q+MzApdm!~Dtqah!xAXiWiTa+=-nqmyC70DaJ9TBX{G}p>_KQh3 za?jF~1m9K8F>+$TK3$;Zi%5LRy6F&3zZAwK?;QH%M*6 zYS%Ob8r=;c$&BiHPP*@eUPRD#-p#|N8)tI_X6c_;w*5y!9Zn=`_rF~pWperP!j@#5 zmW7U>yvO+%*{1;s-|_TWvHGzJJbP2+^eW~>PPccR7_KnvblTq zy+8f5H+rLFi*vU<>kkMhPOcv*+O^(8)U?oI;{y`T| zQLJ?q0lL)I!C(NU^GXT(^x44lSjF4$5DqLG|@vO9{z=5QmBz*LNt_`vs13aE_q1jW4u1G_NG{5?yi}lSuL!Y zpNW6S8E>V8Lm5-1+|1h#eOr^`FBG+*=+ZJrypc}Urlch zuYSEEnpahC=h7=x6{&2G{4r23W~HF#WR!r_4vB|0l`I~gt-Ktajed+`A^;`d1IjW6 zjn^bJeo*H3mS*=Eu$TfzbvJA71g@CIr0IAX7hD|%{Uw?Zhppd+j1lR{%TPPe!=t8+ zf#xZB0KgJ*y^f^Q(q$4mj2S9BdCeu)m>d>rkAZPa&u>}ZMSAy-HuBYN$%XagI0kNa z)r%pNZ5Q)5n~r5-F(2fpLf4-5Ke9ousedtXP6m<#gL}-v(mbj591|S^D+jP`H2L=Y zr{+&=bXIVhaGN+Lp18)k2>dtz(++@&i1kLV_v3kqmIsa&Rk`L7&f#Apc^tKOEATSh z&lT!3cIUa$^F7k*cZ1D&*aP480N-77dM@tG@5{5?%V*y6GEkr{k_w~+0xkm&IF*)p zK`G@>@Zk!#!rRMu2i!(4KaL3-tY;_IM(ql-+4&_6B&t&%|qQ z|J*JxdZwTOTTJ=sqki`yt-AJ%le}Gc2jCiDuS@I5*FW{UjuQT%unXCa_)f6o)xg3& zu3FZXHnz+2wSx2D*Fu25i_@;Orm#1A%5jt^sOSN33EYu$ z@jHR~E;~j<>xeL54rT4XA8@c%NOc1JY;rkiA6&f?`#Y_g{cJSOEbu~Cs1wd;%>wCj z+M3+)#GU=j-62x@puMu;b=qjpXf-*BpE1YPnQV;y-?Hc@>PP)qu8VNCKO(}vcXsJ*t^NBk7QwX`n1e_eFC898~DiM@Mm{1!fDaZVko!N6W~2c2ij z<4tO<1|_~fi_s1Rc%g{bXFIuroT=%TJ8C_@6ER?f7^Pc@&+l6Q_D!R}G%(6}t7111 ze3OBb(_UbgeQk;0HNbB3BmO0V@MC%`W7=JPGlwK__F(&Yz?p40_ynHIG`RL=CM?zZr0d)D5{+G&$ zAL%nfRW~LZPBo3wBwVzO!fi7OP9;3{lUI7-HRTd@8Tg(MtsLTa!cXv$b-3@dTS`1S zZS<9$@do3q%XWALX&#*u0>o#{=2f7M=4Kh`>|ywLrN(6CE4u*j+<(vURrDi9TSc=x z4^F1BACq3+nJuUY{J$H<_5TOz<@1j__m>umdGvP!{DZ5nZuRgrWZ*0BP5F4FY;%L4 z{FHt%?{}I&qTua2z*dH>^lTCWV4zENw52)SsCOV@ITr>Zq>hKO#jfkZG^c^nkN8zN zr{$6>X{N;=3V)a$zF?fZ?10TVj_ub6>{|ZqFs%U7xeX;-Y@isfwzE+N`Kf&GKC@C& zQKfi5(yUzv$`G!^gBL@_3xIZXl7X|;=c+9N%4hvg{EGSIp&#F#`|ZZrXo#F3MNWEO8*xhm2(&7^GtF`N=V@+kM2A_77&18uBKaHjP>!mL0l(qxY4BuN| z+l%8ll57jReE_tk_BinsGu}Z;3FM8EbzI!rT7en_;ml|5JbV*=2_xx7y0P8rCoQ5i zZKg$#|2ui}r^HNaHYm58E1#ifcUEo(|L*WNw7j>6t?uAr^c~{hf(_!h4MBjSKeem6 zoCNlD+DM<>PNV7vP4>j>l~bGa-k&)#$Bnn&iTsHW0rlTI_Y<^TJgA2)Asd>T3U|k; zvy@Bab&rNJI+ovEAFrw{zW~eMlU*Ssm8}cXpr|Y7UG#EhsT;u>AK`p@_v8_N1B0}VyM8Ry4yD{RtR=r^}uVp06v**R5n z^sw#nSBp*XhtKndKwBAYW}w0?5Y7P5H5M#aFm`^YCRE%-16z}zVl zN0`SONY!VJG}{fM4!ZMz`Chk$@6dDDig@`7ZWG1zWWTx<*&Dm{(P6)Clr}$13+|cz zehE6a>~eopNS&=!JRgQ#yo~|;o&s$MhC+14As5-Z-fm!W`$(whGUKa%$(hQD zp^~2~S1(M36nNb_7_fBqh=UF}TE5}C9$`sP8eRM{_5;@?0h0rSXFJjx=fQc~w*wAj zF%MfQ>)7DTD@9adTTfVi<(oHF)aq(2{=;+u# zoj>nCC#>Z27B8@U^)@ChD{5A2Z$bXbN`i_hHn9t>hDRL)2K4?5FMk_<@iNGN37RuN z(1ZY6Y`5Drp?)2*_0U@zQ|c2L*AFj|jQ`=xT9Rs|n-qaN3IA0%9mu1tV~Rbt}VJ~7+ZFRxOun#gtj(kz-UxGC~p986bR|ICpR;Lw!z zn}UN(q?Y z>13r6JkaBWIS$;(FwY3aN9QP-NLjg~FkdL|EJ4own9VFtNh8;?wb>2k{}nBVAZf}U zLXq|o@(q)@y6xbER%uBd4j;c*1epw3`_m(NfUz1D;D9mOXfcPJM;#ASg>Dtg9;R*b z7j4RcHDJqsD+<#(@oyd&EFtpbP7^7%D&I-Qw-Db~cN!PJ9LsupSvYc@0`H0htRAag zq|wQn%89B8$*aK7KYfc=CZd&UfY~Fk`R)3rm2LgvmXRuGC{nNcz*wj9=GF8XS>61j z1MiJL7LU1{0NAPZ@nkC!X_EP67L^8V8BOPP(Ct5TIx;H!E|vvW z;fhAXaz@Kxe`a+1cN}mV2!G5KpwZGa_KDu13r>6l|7tc8 zix1soHiXG9U)$@Z4p)VUH*dyei#189pHF6UZ!Ns6WOA?&Qc>f?LxeSUNVjBfAO=xI!;s*oHuX!^jOckRn5v`%{unMGthn8S6%jWkB4p`9lrRDw*phEu zy;hblIuIA^CQqaDe&qhhw@zjU0E7QAZqLv#FGKg%%qV=J?f>(jW54EN<~&FUI@u_H z+60SIBanFge_^f!r%Z*qt?am3hp16T&v@Rp6|9Fzrd8!Dd8Le~p~BvQzdC!@_1zjQ zAS(-?2cE+-U_^lMMn$xIMtxGX#wq8tt22K8?##vI0}?LiXNGcg%tC>%r3W12WZB6B z`+vL`KO$~=-2B~rx({be(mnV<t?L;=*X&pn5|u?I9Q?>D?RIB_R~8mCck%%3?T(dd_7zA+<{Bm zt!6BJ%}UX>1_JVLK8O4UMR0-9!c0DTw4+kSraHRu)~u`oS4c-0c0};7%vR}j1FAb2 z$6c|m?;bbxX!uZJQgow^|D_MAzb-)c$DGvIRy;n61a1JU&T%_wF~2FU+&ROR49+-c zb{9k9U)ZHUK-K)U4F`2jp;`XVfBwfh%g)}hH_$i8F$f==YnMtj@JAAwO_TtGtw#9n zw8B8`-o;Jr_0b?ls($H=`uJ72P-zr$x4335XTb@TtNrtq6O8kW4NlQ}xOBf`U|-8N zi{qI$!jp@Fw15*nP!yK8km}a+Hy?OsXSl~K@A^x1hzWTa46aucBBd9x%kn-aeP~=u zThE0hO21TqW8(WCBJgG#0OwsvHpiGy^;qZAIr9WX46{E2JQoKGE@D~<72@fBH-H&H zQ;fxGX0N?#L4V&)AOqrY#WyYg0xNkXK2}W5)S2JrECn)Kgpu3{zpxzJ-Nr->*=dz< zFaBq0O7UYt=}b6Lz-{Z;5PpTMGTX$d5-TWtqFvT@gntnxCvQ4>J1#ZJx-{2Hd?^~F zI`qxG;Vc9u<|zg~P#T=#Vq-z8dU_(!x#Fx_qG^}|jOEs9(p8`>GhJA&cYn+M+y#QNshw9eeOIU}` zgF2&Lh!=QzT)zWzsZ{Td#KFY6WSdEEUs+5!B-A;T6_bohq%&lkF*B^Fuyae03eV(Z ze8`tOs3C<=kO2yyx17pP$50dg2yTh+K(15l=;|vOQ5LQ3?cj_01CVTlI zSeOszN4#qpzWFzxV@v^TQ4Z5_EVuBur{)WHL7ij>OAyF^5oF*Fv}gn#^dIazuV6o> z71{r|wl|S~X4qC4E`&jMWD*7RB4QdzP`gzDhE~b6trsW9e$N@USm^Y^4fImQV%6(( z=MDG+CeV6MK)U(s0HFD{$zC^Se!Yd7UVH+pe-EO%nKq&HV!-{iRG>9FL&oC*gdh!k z>&G(rKG!bYz<84Nl4DP^Qg0&ks_JIrg^~#3WGuzq}%d+B)5hJ~e`;UA9G4 z4=w|bHB%n(;xg=Q*9F!E2yvC;l;^lJyQ#t>@!jL3{-UggadM1e(e2k_Xd<6J#rHK3 zCC}e32aPIK-#GaW^gXyfMWwb$%7Y)vIt+N(Z!`eaXzWC`Goous_Mpm^lR`YS5%$B= z;O&z62)^l*7+=cyqR#K12pT^Z!>e^*batRpOgp}{kaXcHinb-i7E0g|{qX(aoF!Es z$!JpnW$j4Oi&vg*OzA`^=S2xkdTVL80JCb8tTu$oP2);Ozn|)6?$FliK!6WCPA|JB zx_2P1=R)ueVeD2qLaprrOjF4Qg~wk$u2!xTunNkrA@Rzs;`aw#0LmlJ4(R zpc{c7r0=>)RkNZ#`r_D7wICB!lb(1r{90V?RH4AF4J)iwFU+~LzMEwQuX^`;G|IzZ zy^L_}#<%7T>JZlPEBtgO@(qHo=7x#LeU|LZc%y9C-Oeb-qxw5;aWqS*8rBy((>sMf zt6cnlqMRZAFVF+C$MZWziV6h-6)#kXE|eG4j_7Se3b3avvx6{^^HC686at7KI`rw* zWvMO%n2(;n92c$@k;KyM!>_i;N)sN<<@UBn7Q~(rz%)Mkof5k7RPfVui@!Ig+>R^4BtLUA z30K3bi1F>9X_>G5R#nM$N=)pH-&3(p=F`i9gttzL__NGH4*;S&^H*HAsrNo1Y zf(J#lD8%Qp!mwkR zAfL{3$)F(3Elzn6mqJcp4vdPQ+2vQQ@uWOif7pekc@FF&u(HG%m#aVy4`a;DTV*MD zu1CXPzU%R{+&mTIrLHjF8mW_y_f$E3tj7)X#GEqueJBL%*xKvJ(l?aHO}7y=XPFf2 zF_qkI@%*m&6NXT_$y049Tj`ghR$sAdf8#lRxb{7Hn|uX@DYQ6`|7-}r|0J@#<|3oA ziXRC*9KMHklA^5i&5Um~?{HvpWj#Q*ISjOaKP+Rh${YEOo>%#g| z^uIU;_+7v`OXk2hk}F|i%pIobCVsKzTSBt4ce?!mPJvaAW`Y|mXmzCM=+~;h_Zh20 z9&_PhBw5IF%l9j{P1qs+-zJDQduC5F4tDBtE))vcYI83vzI+K--s&)QGIBLmbTk^7 zP3blcJn)sRdPNZ5V81EHFD*y~4freRrznx2{7&Ri1;Rh}1Q?DpQR#Ry9bbOpai#(v zuN&m6$l0Ap`1+v(eUm&yuAFS&d3 zQ_eTWDXD1W@rlFJAL{8>y;JHu7s5ZMY^&5%*iX)oLH@TMv`+o(<{Z65Z?{lsDw?%nb0F# zMWb~>T+4vC*1y)V{isyUzRk?@$mBPU1S17D0Mg>p$!q2E%Q` zj8YYk54rjGFnEpIDR_Rf8$8A}Zu!dV;#NhJ;Rc}{D^xYE#E5hCHe+6Jp}J5`QL704 zoN1^@h`?3!j6fWRg_}PWCr~0v@4ui7L2cDv4YPKvnZw%OXLX!k816*6FtL7yn}|E@l+? zaT@UJ;u^=B1D|tA)^J=c#CRZZY)Zc0{=kG+gJE*}!F{3C8II792T2Ugi;X0#+}DZ& zRQ^|mU3fpE6SGyXd3tY}LK0(k%lO$NKc|+GSFw{^yiHG0WM!Gv`+~H1n_(*tolF0@ zI4uRX4@?gzU+`59+-@OXK`mLN?FHfWa&P-(MI^%YBsk>y!RNF2=j-wBiRMFH^8Mm- zGqE_^sP{f9k!(Gj;q`$(GQw%D*c{u_J+h9GqYWMyn3>^dE~hhQtwihu_9Xb5Sa6HHa2OMdRXZ(l-sdp z>|I~E<6IqQ&#);Mm!b}!`%O6deh|)+nsUTqE(P^taqM4R|*gK%G{&!oXnHJ5D>0WE)&zliC2 z_q!Y15WWv?)6ZRv_Se0z7v(BF5F>9ULe`q?kmsjQ>)|$n37I7%I=;2A5=?dFw-q-5 z)M+>$-m(&Mx*BS*8S3sUGhC7I)DLD~w|1{S=fodI!<4FKkZvLkyfM;8T7-)zvJ7p8 z`KSRCX2S)FunB^n?7;0kUL)}716>C!9)}an7O`OudoAml#w0#m;5qD#E?q4CYRMjn zd|G`hvEpg{;1Bf!4r6JhV*|nK;=hbL#3vpA%fQ4B6$=yF6gXg*X|+ffe#liNT*O=7 z9jTJhQ@l=u#hk5Ac1HjF+H#~e7MMOEKIgzX%(^jVzS93L+7>r-}miz&UlY9LRQ$0geq{v z9Qe$QRg>k2UJqW=pAd(n+&mZR?e>r5V1b#6JEPW7s%}_me-=IFd~rblJ_hYgw~!=A2;20Fxrw(8c{4S6~JIjaa=c-cMCpiV!16*V%m@BZgg^&WoTRwk3L}? zQ+Ujn`gNXcJKPa7b+f3%%Hp#n5jBiBj@TKU4*npQl-D_sn}?hN?;S&UyMmNIu`#*N zPhax^*14X|e!qSmyp0z>xnoV@`E*Z!@+{A16BQ8#i2t)thD^$g^G6Lq5rYZhul@Pm zoehk|2>J5ZorWJJGHgdvv-ZDZEu86GW+eAi32Q}aAOgd z3Qp=#>1E~DWF`Iu72bJj$FuV7Tf+Xu>diQZ1MV1Y=e)FjqGBlA&jZE)W;s}KAnS_u z?SrWx-p(i7H5)>@_qs^Y0&huJMsi%iWFQb8I%mT4#+~N-San|HyN+F-(NMwdx3z(w z+vzgqdjthvs0l^}&<;7^D3ML-bzVF4E)n6~S&=)$03;gtYrADYbLsbD!OVQ(N2B&m z8{CrPhNu>eC8>eXA%Lz%bn8koN1tQ7Bk(CkcLX?WVC=(HdTlO82}*#q1_DVC{;M?M z`M;wyp|K~_Gd)>bT`N(CoA_tc>l{JXS)c*Tk~L9oJcs;~S)6FhQKMavop*ZAL!0Of zrv8T{jqKr)yyjv0Q(SnvBPQJZg7rVS#kxQsvLT|-FMslvqoq( z(Zc%fN)>FSXoGMI1EWVWof@lRSCtZ2{DHRQT_=LO5x@GtXrrTUQLWguRw-@pz8fL=^vtO5P+kg*OQ ze-2`lLM6<6-)FO+f8KrOCAB~f8nSW(@~1$c7wC6$rsH?)g*8^R;Vc310RyRj9g$S0O)>cCnJqkU%w#Shb%c~4R z7=A~~b$?|1`G3jy8R36q{JmdEmnz-xHeb&W8Js(B3O4>b8K3r&9fiJFB5JWmNq*C! zSPZRrYPBrrmKm2Go1Vx1Cs9bIon$!Nc<4;Yk1PB9g7%@!&HIYN zM(OiK$zcoR8tud6n$y_3L9&*Nk)@3TL>i{I?2>wt5sz_!yS^-g@sm)5cy@4>@6^B# z3_Df7KQ~4$3!1V9@Y#fdo4j@Kf&wtmOTUeODN}t#3O@VP&W@!N-R2Kt4XEndttF;n zh!jESI?j9Op}IW1;B8KuAB{e>(NNWv0{xawt${M}OOk`nX?_yrfODSvXWHZt$vxjn zq73%p&&OWM@5ZD0EcJ64l==tu<|ygqGe%>77yE0FIHN}g5X*z+;v_lP`Uugd3|o3# zxlEn5O;z$Iy#*jCoR){DDC6bntJL5+GtK<~Sp}8GvI!4@MrE@>5om6U>^CsZU*g$t0;?H`B!2pm#9M3IXbRB%G z9ToAoE=L1(=QT&QTiC?nxJVBZULPi<&xv0`ge-o}XUy^2uaMZs66M>R6HX=%i>>q8 zOv8Gvzju0MKt7Z;I;SItzP0gdvh`qfu-k;QS1IeuRpiJH&2=D2(>rc1*7@RPD7_zO z4EoE$izqX$H!>u>+I+vfR&xkAW5^VD(P{pTLc%&+mys{tLk(aT^q&?|1(9`_m|q#5 z`YsqRoD6;#X%~BW8_4-^={sf;6f0hqQm^%w|0A*DA;Zt=LaJLN*M#?&+uCn|X_it5 zsQDbj@`*6~HZI3&`g(p%Dvr-hZ(W$~4pzTP>LDzK0^E|wHQgCDi4<{G^Ivee%X8{(k3Qx+U1%12*ZaC4={5&F-o$qU?LD>8TQpU1fu+Pw zHuXN*x{Td|dco20wIC_-(8d%QX+f2U>$lYb@^L>AW>Zz1n#+3d#1DsGNRVk|0Cr^c zHygISoQc`g&PiJfIishbAEEJxyJGlb5nisi|489@&p=L6hSxAH#-S35YHB4r@6(?C zJnKM(EFgu@ZY56{NsD&u-aPzMNH*iXUG3I(0spM(@|(bS&dRu!CqNbhFbvHh1Mcbe ziRQ67&yKEa5i}B*nRk12xoCK8{?Pm+M;L{Nq7|L7t(Iw00#aGBSjKCPfT54#rMamD zMMg1L9LIPals6O=da#j>(qNbuyi9`@6AM#y`<*dt4oUr^X9Y^Umh!&4Tw%2z6hyvG zuty&fL_F`dR zWgH#@wPVvFFdwq_KFy1fMRh$=4IE79sNP&%b^-7u`Cp)K{#v^C+WK9;i3y9%Y$WY* z-Qzi!CxjFmC0=75E=`w}n=3yHp6g)~J}I8lHEgLMoGO(7TGxpi2iR#e#Og&mwkvIL z{NlBnrKtQkd8mfB0RWV_onT;LIJm)2ZZo zcSWf~U@#zsU?^JZ@Sfk%ztw8lcEXnl^)jRh{aN(#c^FtdHg_nu+{^nVfckS5`doJG zp6sl|dH*-tE!@vk=36izNY8*gHc*;Xgiq}RkYIf;w0a$$g4QI_R)w_zKK7RTQa+6z;+J5f{FV$j8ynI1eLFyK ztjnrCU*eAvos@K=J$)_54hfQ>4a?Nuo<=3>t^ShFxE?LJkL?iXg0#WZ$1Zvm^yZ}joRkj)fV2= z>2!Bi6dkLan5LK*a3+hWyAh0fVMV#(aOXUGVYk>Ra1`T^M33za5ab0hWb2n9AW^pw zDp4ey>lXe$5egr`DQ*`yB*GETKaE~EHQ-<%CI1&=64=GXK(|N1!suBzgP-QF&p4UH z9uQ4R*ut02Ms&ic^QSK1M&RDQ%9Hd5%Nt##-h3Y#x*eEVt%Tdu)hjs~vIiyI%*0I; zIg&I0N%(0G2?z>bLi_&nAfEL*;5cK$<&Fxc?ZXefWO&6iu?;TSJ)EM^ce zh2^Ye{CvE)rkovNyTnUf3|r1NzM}8+EF4_PRN=y6rNvZZ%2ZlQGwukyjv$Ks#3fI? z?`MlOzZH}3EDz1nuLWeZ9Vt-WtzUo1e%uZ8JpvCsbd&YArXG0_1jA367D7a;JQk;q5TlQ ztuA>tMe^%go+9FW4RwS=@`l#nc4uf8csC zy3{yJlKx?o-Ixfr-VZhwJ^CqWCXLPWmau;lnA-#|!v?n;_|L9B_AJxw8H#QyqVqPV zSeuVn(LQ&)@A7zU@Z=r85upD}n^}WkoRJc=((;z+j2Z;gde@Chc5D9#K*#IE=>9$1 zEq908eA*`(ETt!QRT}r8A7~el&hakUM+Wm1nCmRqumqBb>8nP|<%geD^$0$=yRvjl z5ji*$&&ly^8)RxY#AwYG`>J->?h?L5T94$Dys zv$lKP@rx&ZA~h!nD~R{VA5*OOS(j}rb9tHl#AClrE3k}--A7upwejd%vq9)!v*u%~Dj(e4I*O(;YuuZ`-y~97!?rruXC3$=kiYH0! z!+%haeV_k+@Z&jIH!f|oy=mD9D_-o|8aWrPfU1HO2G<2u`~p>f-0g{vmr$ZDX?AWv zx4o8Jk$j4cXRs90oa&>-y-M*G4f9{R3{3jWTPf!KH;qu$9LlyNsurmvG)9lat{ku? zJi510!NKUimt{OnJN`DUjI-6e&hBFx&HnS~)`1|w! zoW=T&txDLLkY1e9qO8prNn7z$tE`MOlzU(>rR0xs>iIwgx1=HeJKs#lf4QpKh)1f9 z6hMXMHbAHMBJ01&Sp~KWh>WY$e#XzBCwzPAyDUo!(Y$EeV@1Rw^uFsIbVxtFE@>hoB7 zO>8Hdvvupg!cgzQ_YFf<7UA$+;JWq`?EOg*>XZRI$;H$;>nksj&|&vmB4l}tVWTjB zRYU;e9JhCXr1NiMu_p%;1RBde#>vqE=o(cVFAU^ijr0_)-iTYEVygZ>K*cEn%%Hz; zB}fy*;iopmp+^p>{3FYGUXs9(0!`Tv_idj}&p9`R!{c`Zy*>7EfGy}kTXK2+2Iop> zbbGD&vH$OjdkNA-*CBVL&_48TVWm2#zAw9Jk?`!wvgG zLDA^6pR_I`lnb(n$({-f9zmNo|Dz8YOgS9^eleK+L((jf25H5(>8b-c zKod$s^Te|l>$dj+-M^uI4JA2oI2+_7w_b5ENLy3HHLgSwr`qqsJ)0YzSBYc4t!yag z^nf@X`;}7zIS+Q_I~DW}ExTP9r@G~MqsFoc`Hq5!Oc_)QTMP{>!9p7qeUBqeCkQT( z{H2O8?}`+aWG^mCypdW=M`E7>2oQgEAQ$vE6bes(J>1A(c?~QSy#8~$!gAg(%XpvR z!2*XqWl|yfGbQ@3Ty(R5d8MKz#ww&9Z8DVM)I&|MOMg=Y0Zj-^e_Z*FN0f7z&m#OS zHrhQVJp}Fbgu>O+w<9L!Eyrbe{K%xOpw9Rz0>vq%et#(fWAme_zSYajnYWLdGW>>- zKUOg8be|K5#lFn?tcv~ctCq|Dyz%cH^C?l^a3q&#Qw$Q89fjPQ0f?m^s)p;iH3?=; zhG8y6ESU{rf`+wzSM4xpPNi(SX~Vb+wx%F%8--R5)zLlB zX&=!a`wKH2dH%GS39FsGrBfne)7v*on`<;Qg9mx z+}I4jPfL~|Vt2u{Dta?ZU;)u#2tDqCUq=3tCnLH;;C557U8?zA!_J8Jtm@$|Z z;hVuhH7`%z7k8BrzGJ$=aX+){wo6F{1Mw|aMk<#E;RGW`zg36;6mRfJI)P`(uCz@h8Q53~^{kFuN`ZIp{7KexEr&e-R?I6Rv3m;@G4V~q<3vT{`ckg(5 zjb3e6pYNF|tSU@rEhM?&Ip+AjZOn~3v1hCHk3=oZTLyPTmo~WPfK>y?Sy^%#Z;MK8 zAY}gNH3_NqfP6E4)HNhSW+ZgWNlExzHVy2Mm+ua9hGrO%4YjY3u2WW-1N-{6vcbUi zivxc9LT>fxAhr|W$O!AtX4;psihG*hctS0z-CpLbuzz?sG>JPL#Li0Ttr>QZy9s=^ z`e(yAG|TUk5sO=(7F{Nx0pD=?R?v^PN>B{_7!m2Ou_<^C2z*X^verdNLbVU95W z6Z_az8a#tO9VjE9IG&d7S(_dJkXVD4&Nhcy8t((e6YvhB4U3fX_Vi#g+lkz+eelY9 zFdZgLj3(-#f7|rShL&HbC^Ng;^Dx>>4`(>DEWAB~cjl}B!5j0mQ^ic&!cVX}&+7>> zKB|-ePgBS*gwnM|<+~W2!pE>V57Pd&gRy*`k&CC-L7fYX^8*iHcRHFO=eSOeyU$kg zQSr0DlW%XgBCut5Kjb-AC{DC_$nC;PwUtvk7*HCe1A$0;XDNGZg2@OPNfd!VNwf;~ zF~#WdDsPTF+?#Pvj8JX(?DVq7`Hhv|2+qJhyF;Y^a7_H-Q5C&a4yCQk^<&|3?(j{^(%{pJ!PMcF2ANx=%LcD92xQC*T|8=AmS(Wq{Z01X-W}P(ldp&6 zNJPL~)R={aCL<=Uza*UkhmHBq%U;|jj3AP*Yk>7me1gKSb_;=DpZ%AyNtU-B0*Hpr zfGHH7ezr&Vaf<$Zv5X^vapKezvEs3EAy4@T-KCEk)weAoO8+zw@rC)aCLgUFMVCr*he!6uH({ zU5?1ss}5|ijs73)oq0Ia@BifKp@42pX&L3y~!dx@n_xrxz_x-x>*Yov!eA(%l zNxn(7obXIAp#iIZO~N+ZNl-pGLe0%Wlof{31yGE`CnY%$*#J`U3z6T$XZRO`!=)MX zBf?V)wxJT0ycO&+Yrs^#VQa%gs?bS?lsmN;1pZVRMu_LA!YadJ`s|=O;nQl*y!?N{ zK(pU&RJ$_BDvAitQBq20z%?l9- z+|LnTQyKNu=;K&|3--_9Fn3I_`Y&i9gGRxchxoto9D~lkkp=Mk{{ykz->W+1{!f)l z!zMoVveEmMG-ZZ`uGfik zfZz?V0=o>pF@JS<<*!4bRB`E-L+3V+qLGs+!yhfy3Ri$&=|0})R#FY7{?{`3cv0WI zg*LxymJ5~jm45r@#H)jpiIa6=d|h&tF;oDNZd zWIiZg33`8RZO}l-_#Bb=%|xy4p)ZKrwYnZ)ek!f7$L}_|FMk>0HD~XHpPgv_w4dej zv zuw8Q;v=m@LPLLqRS_zBMBv^YQso> z=+6utUu-xs6?_u>pw86?z6QiVB18X8znA8D;$N}};LXM(9Q%+JpD^)eS+C93J>$yn z2BwEW0T}|c+W_B6&5dY(sX=DeGn9fX%G84Mf(n@h4);u}xH2D~&t#xb#&%WkU2U|o z=^AimUquR55rrACIM-Zw6R5|h2D8%3Eg5?COwXAn!A0J=ue$04+0J;BAN+yuCE(-x zdbpxFDK!#o3(53a->sXp`Hgu6%WQrzL{xIhmu{p)0j;z6PwP@kGOzo=#(&Lm7kFE^TRNal5X2?(rtVOj-!a5{E@X>yvpdx!mvXBHgLs`a-o->s=+0Qx`{x=GHmjyafAOz7*gtPBo8|T* z)_3$go$jI%xCks?-o6T+DDc`}4AT3OVhkN*XfkH8H>VB@#^~T?NAVdVEpgdqgq$d_sTAru~}lr4+V7G$u5$j`*|eGk8r)D zy79(4r^__5s^?EDmg@gJY{E`5%PX;a|d6TWZ>L(F3P_YWEZ}61Hr@r zkGacOG(SBubW<(~|1EqW=jgk4kVkLMT6(%OjmR3yb!%BAF{*p8prb~^etcx?KS5OX zV>0{hr+fOW#+r1LO#-|rf#pj0M(HUSho=BwgCFNzXV_9j?Zs@mi9JEBvUbTV1B4dl z%V*TzE_yOoq*Mz&yfLOX5!9w???>S8(dzVEdnjOdDh5b5)o0s>KaApg8No~NgX_Hx z#0`mK@HNUTW8Tvt(+yMmtykpB6@QlmIYPc@?TWs$5+nVVw*ZSc_VFgy$4|SC?*bu za|}vXW1U%XYZtB2mbllU!fE#{-|)%ee!r zTG~FkdQK$=OP>*X{({YP&sXNLOvtS=%5P^Tp`3=1nbvimaJRj|m1S&(%gQZ)%(KBpYA%s@k;0WAp0Kx9zGM$0wfqgv9ya zwf(8JcNV`rs%{V~Xlt~weGI!c!gjui&zqV5Rk0mc!;~z@u&S_fNo$g;RrXTC6PFRl$8V#Hd;(|{~gm~aiKfI{a90)3q zR2=S?)xlm6ObA?)>o5rpC8;Qktpw36oNS5QVg&Q{Dym%l^e+e~W%ENYj5V@nD!|4H ztWq7l&037vwfnN5rOgCTF7>j7o9K2c^DjOgW)iS2;WGpg)kX9=F=_AX*1RUyS#nDw z*w7{GF24FkHKb&!;f=55Pokz1t`2&$>jZ;RIcuj$T?Arg#K3T?Daq5SG4pW zv2vvQ}-lk8hM=seeu7 z{2G^Ti8mFJOddUyTt|MmB{!j4Fa;d~8i1T+6jN|Gf-LHZOeQWqh^5r--5O5ytec4e z-!4#IK3U?(AP>FC+~SWTIHS_OnQT&k9j}{5L~Lz@VzAjEm7foL;~vwKEiW7rnr{~JL;Jk4_RPY*E5@N@ z;_ijjLYttoOg3JQ1rK9C17ot(p}wTWujEA4j;zk+!qa~SWdI7OncLG}?x@!?klEI1 z_pQ?p?r>@7;CmIU^zs=Yi%knrbs{D8I#qP~5~pSPr_JP-yaV-}0t^iLS)Z8t?`DTS z>9EDA9f=zQl+Hzh*B@Vx!vUH6J?ZNd9@|f|(R&TSuX7sb>v+I{`)NiTlVOLMj*j`u()UxD@NQHa(l z6ynF_cZDZ`3*%;7QH6>y(QgOkpizzdL5}m0f^ahw`iMtc${VsiiPIfD1Oi3P@ z+z;T`@HuNp2tW@dCLh({w7Ep-zqpiw&IQiiPw7K}T%q+xj$&o~ zQqK>+MMZ;I>}x+K(^gsPJ&cfoNr7;sOqGwo;44Tzqa5o#y`0lv7SlN{P^wZonQ!Q6 zcLDIs{d9pBI5Zk}3Er*qay03*D1D_*D&|Y$<|V#4&4kxfdXAsd&*zRV4*)7OwUk!x zxI5Hs*2Nt2k_Ll2Vj9A|U9UdV2A1|{pODtPMug(2^&B3Ko{GTJG?KP`s`<_8=;(Dd zAPH!9<2}M6J8r$1;4r7TjBf3?y!hNHNW1l$J>ZzujOUuIc;dT*CklU+S(HvzVCm9b zG&Hh@+pbHbsBn_bx(|~i%=(C;jaG+A1@8ZrRLJ>Yd$@_Y{-3I;jGtd{Iy5D=AOO{} zajW`EUZ8POWy9TJPBs*V8oAX3s2JNSKDvGEPyR_Zm3fPm-r{%i+xqc7_d`K5wQ+2x zdLZMZWVOSqXGuwV-4Ps$?KKVspHP$>AY!+`9e_9_i=8qmE}# z>`LzI;C@S}F{09NugEvzn-TxUAjk5^X}n19T}z3QtP9 z6I^*J-(YgBGTf5&$yugb=2zK5{!j-u&DT_fZ+zqbkbUV^Vixu<9OVbXU6l!Y(D>%4&z0~s#21`sW5VMviY8}nRz)-7 z)UbXa(m{a`?@q-zmlNlsyWMdWhfB5f7T!;5HF3F*T|hGKA7Is!>FGtC$LzO|afHF9 z{C~3u@JnBBR9lZOM*RM!0T~=WJWipoKKid>ECwE-TwXv<_3w-4g3^EOK#c|eZ~goq z9}maH|0RcDrYV8Z`MvX2E1tjsR#*OulzSVxBTl@DTV?agcQz#HmZS-{4 z2tFEJ0DLn4zQLf+@IL`Jli&jxf{0Oe)? zA+zD)e^`t+`5;~G$Ic#7-m8o3|2pRd_IjmpJ<^yASq^R~egLP09f@y)Txo}pARuOo zl(g-$QeFsMeae)mK&XQ6C5U{+$i8;l>)dwdGP zT8~t{rrcGtT*J{M%Z43J)VKMJI1gE&mz4v$z3V;VL0U2&?cUh|J00Nl<2lCz-ZI5k z&t{!*LY0S>5b_R%>0>W6z3x{!55epCxO+SEPO=NM|M*^YVX(4|Iv?HAdqQmX&xkmN z0sdDeH0G$XPrMg;*xGZ<=Re-kF8pbW3s_Z4Nw^*Mo_v}7wvb!Zi?wKJce5CdpV?`k zX~M_4w1mg8WfB~Hf+klEVv~NJ&&VH6{SmO^?vq-hy=-*mz6|nq>w&`qp()D~(?0k2 z+|QH!rR#;T-pq$`MFxrEzOG~TPOJ8Nmt^Ib5ef!hREl&jAj>iddIE$weV;LD{H($FKabZ|1RrfuWoU$#)-ogDyakMM8J{)V5&#|V0a0*h!>3{@Lm`( ztBqA+A672~0DzBt<5-=7_aY3~s`h4QU?3t@cK4QkdujhSPQMb!43#Tl*rzP@)QpBf z+>H``0GA11>g!(q?qTfG)mzIhObx#e z{sJ?o*&s2YQm+9Vri~=i9L|;J^;-w{W&l(#*=3XP0I_{fVh;SRCTgtKeGnX=bK!H$Z+oU3EjhvczUvV z5kP#8PqV4`SxA3xj9dg{x#OR0MVzNlEzc5qBt+M{+6XO2(In6@Io=?p`5}cV6 zYlWDbnz1#Shugrg*hLH=o7Np8Ha>ADJj|a%r1tjPt)1h%N4v(l8;$FdLH>zS-^+`vl!9JM1@A$t zXJ@U)%_ICq@PG3Tiof7<^FJ*V@<(&GJ^mR9OeQ~p%8Tav3fYa<`6U>72e$mK&&;&! z#*PVXta<1dM#Dmc*Pq%c3}KOW`$V1bi@idv4A_jqwKoD4^iZCfh*8yAzN|)gYrE-Y zE0A$ET1~J8@I22t&k0`x>}f7PMtF}O(%e;_z0$y4W2^V)jS0UL|Iak2W8KErDikps zY^Bw5aP+(@kIr|*`xjq2#roDBMv@(wH*Mafp*R59uqZ*8ts}di#Ru3wmYg9pNsFQP z?}mp}A&Sz!1I}9lFU9xsNGOvrYt(k)OK;-a}+FG9q#v z&%ex6k`mRi`M%tB9C#i+3UOO0@J{Fk>t@Je8ZbO1KM%W_2W;n3)6~nDHFO^t%cM3R zKz(kr_rk_vy-NE@vXgqqg0tE4yV~{sH|^LH_9(h`WlV%Izy2(4f+og3{K4y1KJHM#E=x=IJljcyBAB0reKu*z?t4LgR;6ccsnJ%jnlr zEVDn1w;WcrCyF*+cC6c8Uh3kj)}gwp90j`83jpnPo z&9`lDVV9%*VGCl_-6(CJ!O~u5w=&7tv4^!`;q%EAG$=vOltrnc!A8$@k*T@meTT^!MNU3^Z5%fim$ zs=3dE$sBcJn0_Vj1&;@yi1Y3*LVv&Msi@Y>kt$ATSW1W?#Kxj4+|G8luY4I&oxfl- zN6GKXYB{VWpE}7j8F*B-c5()7xhcKb>C>FezTEiRw7I0Mi@>%d_N|GI6F$v|k5^(O_h`?}vm>SlCr8_%m_z9_1CRYw`dn}-Az>R@-G7#g zeI6+F-}7pDY9OTMJhNRkzr)UOVM)#?P5(i`jF3sT3uAvK9eQa(2TX z>n=)XH0=E>w-en=FU#f#@*7H%Ev!|&P6FVS3=FSNha85WXZ@^@3xGE4^GuD-(ysaS zfs#JX6WxGj0?66O8J;<$*Z?5XkJB|8!fjue+)lJyQvPUn_%1^SU{}ZR)N44Y$79t= z&4X9YOjx;%Y=*n%+JVi#@>SmbKFr*SL& zc0Xm|qp>2>S;KHvoqqzlg#Q-#j;XT#{g=Qst^V)Wk^TSA9^S_Pv-j|p6D#`ef_^HW z1@+8B2G_q&5ktZ0gl8MN^d&7CiTOH|u`O*j z9Ct*896*|;Zz7jbL=-iFwvB|O&`>a&2A2zqR!S(mi%rA!jrW{Eqx4lt)WB=T^*GHR zP^pXz2iU@QvpurVYLEOiD^A}J@-~f;h`LpkpMbSOo~MEA{PbU=0q>w%N2nnR()PXA}i2c~&CJPI>K|e|{P_3S07B{voTasv)t_gCaxTBVXaD zMC8!#Y7i0`d+;aOV{TD$J~8z7WqQTL>pKPWydYxp`Q->Ysi#s{s@0)7&jUwwMa#bEYDQBpeI@#btw6&HN%$nuZQ!AZD=cs1iu8nhkI>dcBnXdOYWeGCE zH16>4J~RWnec5$Q=nlBG=VbTup6|F0>GucPornB?n0JgWR#1$?Vh>hYZ~K$Z9Nu_J znhS_Q0{Zwf)LdGHXS$Jc;<^HBr)!xa)>3ELX371@^oeL2!UM($KsBnV2|N;Ujy8*|6w%bBboK1o`v}XxZlErg zD5N)!(#Fj`+pM_no;MgLWIc$@Q_NRhA@&%;!*?5*!JoN2pmXJ$P6ynC_0~A8q;}TZ$YEp^=gOC^8$WNk{Q{DY3f*W`NR%nSo1a zry36s+J*M7K}Kk72n7kwMMkdqE*tq@CaA5zBA4lt8OzKdbgC)-m+%0EPQ=KKBN8dec42b zLEj~qY2{J^PNsPv;Cwts2VklR?i7$N7m^HB!5lmKEvDBeAE; z`fflC7rjG<3WW;}yVrnspV3j&^WJyA4~uz#cGt(nzKP+mnCG&%t?gC$>5=Zairos( zxejx3!0Li5Fs`Ke2IoXr)q>?|cyM7MW+X%OU>pH?rhP_Y;2CVfm+8A1jg2M`ES^gB zk6~7kV45zTQc*fq(mI=9rh(JX3jUhe z)Zmz=1tWX~4w~77S47ElgSWbqSN43nd)|xWaguh#x08mvr-}YbzML)WC~En8bp+X# z6x(oAM>Dld5pd-=y{N{=YQ*+cINt5Serw?NT^xKa%%-;fV%qp$D8QTVpKtZzIR73P z^`Jz$4GuH#bvo(qmWlvNsjisnBFj0VWQRy0{)|>6UHf|ke0=I2dD?2}v)}wx!IH3l z&Ru4$aZO`4@QSI4H-MA5h|&`r^2QI)A5wX`|@ zy%)S1$;>+gpF3CzM0CMW(V#+KYICx^%eDsWga5u-dj*<8>l{qiy2IpJ$hkGMqex#v z*1DdxW;;H=$=g>k8qYXl=NM804CZMoVD8GJ&nQ(OkT?gW#4u9=xdO#OpkyvZEdi5a z#8Sx&^xn2HokB8OktMl+{BiQXf>2vRqo~5x^DrIE2h~)U96RB7VCPiWi#^-2zJj;o z1sQ>+sYkUUwp>XLc6@%xm}~8_S5SG#cM35>>L`75TjTto@&{m^jf_IX`z4dIUud(P)^i1d2?fkZ#)GFl5BK>&ijb>fh>;0*pE^be0su3=n zyFyTV$Qv3yXODNe=NmV@=_Wrqzxdj8^Q$oH!b1>4K?qO?`QY4DbwKjh!kxM8rY`dx zKz4K8-1})e_)BzEeHFknRMpJhdsrX}^?lZ74?uM7!SRj-P;)8F8?zJu$(`g-n01=| zC!T`lZBwfc@Zf{cVTPzKvKDO1g2dv|>;K~mi||m31@vX#dJEyv+)-pCO$M^VxJ|I4 z1vqjK!!MQeE_C+L)9gz!6$c1|d@WI#u$I`*vuKd;Bja+<9knqf*GLs94Z#Y!H=0A} ze3M`NX(uSbs2EPSF18MvK@;w6)2-O3ry=(Cx7)3tc-$g`_jVo6Lo(Cr`$SLDpFP~r z+_#x(f;H*n%jSnhtl{?2&(2^;NjK;e!nnOQUzR@+5Yp0Th+A-NNl<7A7>miIB7)~U6(v4)~EdY`~Qe5(9B;LVNA zUaOm=8h^vVHI;A0?0o#x%HOKyZ@W3%^myS1>X2w`uH>!7?_V7j(=aua_3d3E*;7s+ z9!F3DzgEW+YX1icW+k%7PL4?jFo?X^ZWHz@N$+u&oZvwBZ@hrNi#Gk&q5bP}?|5u@ zY3Wcd8@>2WZ~H5*QZ%6Z^)roZ{gjji$ov9_!LkNs#|N?DeJ7>>yjxOOQ}ZmJ80g?A zHO`6mT!$->8C7g=A0t9xhUHJc%cSdp=YQPZ!6EVyMlJ^#pA+WBC=f!=E{+&-3|y=M zti1H&jhgq>wvQe>TUw=-pVY(F|3-iZGlDWv<;m6W{K3d|N#?w+FU+^t<1d5$TV#_mg!;riG(nYbo9g1p<4zZ!AEi zd&WPrteQel3QZ+JI#U%(d}h7R1AjR{qs+ZSS{GkOCj$K#Y8+2hl7F5sXZ?O)slH)M z@$2Y`AwaGnEf3%z^mb!Ms#i=ti`DNct%qMoGnY}R=cP2Tx&!yKa%h%F1nNUO=Q~axFYT0iwFh!fMR|#ejaA7@O9H+6hsf2 zu#QL%-fhA-L`%Pf63KE@+ZkU^R_7#}Uh_=FCyUOPb#CiLf=g`-8uBK6tq=C6Xhcwd z*lvQcZf?|MSSeQkx^dC>!`Neq_oCBl7XF7WbCwW6$3;9nuZ*4`CLTnPk#lLuT zJtGQoeoto(ew14Ujiv2;mO-q7j7ZcIc}4^)Ewz?L^iV1RRWy@KZPHS>5$tzK0gCv9 zo8DnX0REB=tNz5})UrVF5uY|_h_Puv&lgP~(BZ@+C`uXCB_?Pa8an$|lt&ffbR|G2;D9v?f4a#?M zlB!w$2Z!J7#PN;O?jRkgT7pdDq8vza(mk4hgie4p7;+lXL#-O6uN`+ za8vVsK(J%B7@$1oiOPc=fVb%Hr*=3KZq{erWDCQxk)6ud<5ol;vZ8J?=RXk$ci44n zV2Id#(ARR}^2;Y8PwbhmnMEx<-V18pf~xhUf2`oeX3&+jth%m0&~}&mqs@Kos+b~I z-?LO`t_eSXn|Z7(WPgS2ZAOf8FM7KRwrGa>7=OtTrI+nn;&|IFUDZ+P=4&mOz|-RE z8aRj{zwLZkWZ;nS)yfMA^B9`jsoYQx%3XL*#Bvn;DhD>bUGSQG1AE9E`@v7KD^;-U z;LXTH+C~U$L>_sy+f?n!;WHMR={`)2o~DH!F*|G78_p5kRMhy3jskC>>aH?LxtPPA zY_o?i{Jf)p!dDl2hcxNHc-1Akl+Dk?M4*uUK1t~p_#tyU>-K_sJLiK7DRVUBXSK*= zOxI>p)*ck9vSh|{)eW0yg=DMW9OzKu6U^xmPjtx8(cKeyMcG-l9#%GI)VS8|8aXjN z?Eh0fWQ<+60}XxW7S-`2NT0n9F$B#k=Q057^xm7S_=#-U0rxXxkse#D{-Uy6XLPe_ z*`duy@Q%H}6?A4Sqv~gadUbQ%OgP(*7u``R!N8jBuJ*^5c6}vtZN}45J@MOzm`g-X z0&#P6S)<`7RWU4oObpi6dkP_#uRa|Cl>G9N#mq0fVN6?U4-i_TSS8?@VA5Q}1%O!^n67-K zX>N2iM-IkYpIEZWO%C&)#-ExHlLkcNDYDp|^x3;tSyj?r)yt&Mo}S$RB|K#mv8QNL z@orZInT=N48!>qBhM=)~%XP5xlf)FIKMi;N*k`J1$4J`LG7m)*yn-Cx2!6UwB+rz_ z*N5+!gzPoeT;sTqJJlI8wbv{jP4QnIPbNf23gnjUy*7Y~SJe{@CF7?2107N-`l;;%sY6#*QB&WG*7| zslHZI40oALB}#9x@m9zz^PwiLnohA~slo=O_VekI$7?{3_fg)g`$fPKq=58iM$rXV zu1{%5|Dg2R&-I-R>~_~<=_NMm-mv{h2#rvY)|gInJ_=`rU>p@O_4!sEV&L4$v(7JB zYdF)@FtW4UANPTz+vmRXD;icU7_|uY+_@K(wbD1ip`bP2pWJ|k^%kETH(P<~>~d!& z-W@;>%7F6eRa;9vl7w#}0gx9LQYqbo71AjPgq;7^bdB}6TOC8tciPUDu|_+FzMwn& zzhzkh@A_yW3R4G7nh&!pG1HgDmKjy4(+}b=E(CPk`wc(U>b`=Zz4X(jK5yEte`J>x z3j`>v6IVBdjb(jlk+C*TombO4(NokB#2xY0?tL2Fxmym(UVi@5WY%jbjp@MoQm^eZ zB9D?=8TM-w>T{;M?$5X-XL}eNcnvJ#)wH0y!Z~YCUy;{bxVd6| zky8QXLF)N*wYC*{La7SawVY9j{q;tB4ec7I}sAxo4V>zj&iope;dxnHRX(SD&F zSx40)WBBuBUL~M;4PHjb*ikxJ8n>&(T(=;Gfa8KugcL_6G2;>*On>msHfq;f`g4_hai&=4}B)o80~`V{9N~!cI*9x-{(hQ z5ERDCwsu5*l6;A7BrHMqEtb-ynFc`_*I=`^ACzcEYIPI^F=v~fagW)g1kk(P`25#; z6g@1nUtFK2OM6qvtPmU~Qn$X+O?-iR_YYdb?7{I~(kK2qYZ<%0*32U&8lPH#vrmrR zLpWupT&+E?E4^2=OnPku!Y^kEx+tQqlDb5yfe1rSwPU}PYoJ1<0Vnn8=1q{1evG^o z=jX^1d&eK=9UKV=K8HbmGQe;1cQd>^H5{mln0{l8lpSEmHH?yjx1c`{< z8quv%c+-wcION!VN1g2Zon_IaG>SUudE&M0NW9AR%24`};t=X|{h4)O?DiOJQdIFO@pL!W$OcVu?7#d?}?Otdf(3nYyjfr`Av zQzUWP07?5Ty!G(;M+0DE$8Xl;w_12VojZG)>}9E{ZC3Apxh=%OwYi2VGf<4${)5@g z6{E;6@gu<_7mXVNu`_RGQX`ag{+vvDt&7!9vherEUm~+?PveGg?Y!UJ`VCpDab_HD4YUrKg^`lo* zDy9_Qa}haR-J{3{jBdna*;5}tazs|@gK9PZkpa!ZG(_&{wG+UpKLd7HtcS#51S4Wc zDvXUADD%sbaTH*h<@j|l!9LXbFL1C?UkW=dt{yOO$iNuR-^{iI!R9mCN79Y-d~)* zct8WQ91HLt^1HO++sV^~p`>Vgj`gH!Rbk7{pm*fAzpCPF&eD5Ywb^!Jsw+a0{9@kGyHzQVYNG zuol6Sw)&!M06j;wJizT^-%ujs9ju=`-|$_r=o9*&c?^2Q8ys#Kl$K4cvL73CcFKa|@~uwk9m6lIt5O_bI>O z{U3efDRD#NUDFOot@7dAOV>&d&mxxv-0FdjLF~)b!*8ZrOnC0^RZRt}C9-lg?!5Yx zEHF5&Y6xtRfq;X-xDD=vS?_9DS!9#{!8ScJm0ltI8br4ckp&<>OX*KE#oYLQuCyJ(e1g-MML$q_JMf`H5Hi$f2YLl>3Qf@tv`v zQ$Z8pyRz%rQ<3{T@j1P{#2(tEKjd$m62Oz9rhUU~Gcu;G{1NF3&(s5WNG-uNTp}w= z_qhI9bk~5bFjRR#CQlxCTx2Pcs=Efb^7ZQ*&kiU<)5!jivRyU?qLgr^B-L7!X$S+U zzMj>iIApe)FGO1etSNwko@ufCZGH)Ju(laYj`6JDIN?vJEPOB7nf0C;%zQ-%noTQ8 z*$yL5DZU+}Y|l>f%s9Um;vVbNs*1B}XcC?R^%~6Co$PMbTo8`OkiIo>b=YjyN|y+Y zkHkG7Rl3KlSqn>mp~|}(Ry*B-`!@s@JVD0HXJlIwHrCl*Fkv5A-c^6U6%rfyN14Ip zne{-qLkz>c_Mgi}DDFE(cZ56mfBIhHsS!|`kw2H_&fBJ!YFTl~*!x>%cZhJ?J+Nhb zugG+vWeTb!N-EKYLyr>5 zQ6!}q9cZrZ$;0nD0eqKOhsnh3q}Qg`z$%t}O-1Y$qwLOQ2>ii>BSUJ^$q##mxGsW}ieA%#zMZUL#E*yg8Gc}Eyrj{TdsKsW4kThU{n!p&yOXxfMZ zWb-E--c${JH4*(vMk$4|h^7fb%19RG!Jc;>{zB7sjdtfdQP&mGkn8l_vE=1FU+Vp) z;t^msz9QUDpzWPsaR-fpnE+Xf8^xVedJpvxCN%?~;(K;8=p}Wh7~V-Zf)BWS j{#(iYH>)RcI)@Gl(`4h0Lr@M5|6+L4RIlv1W7Piux3faz literal 0 HcmV?d00001 diff --git a/bsp/xuantie/smartl/e906/figures/3.vscode.png b/bsp/xuantie/smartl/e906/figures/3.vscode.png new file mode 100644 index 0000000000000000000000000000000000000000..21c9b1be8902bb206a88aec49b6b721df66518e6 GIT binary patch literal 168160 zcmbTdbyQnH_cjU?N^xm%D^Q@t-K9{hP&~Lpae@;xP_#HTym)bUhvF3XK!Upk*I+m8 z`}^MeefO?)|G2YOl9kMv%*>wIbM}6o=R~TjD&S#LVxyp-;JsIr)kHzT$VNeVQu6F6 z@)uQ4B?9CJs=KCw3`+SZ^)B)Yx{b7oGzv;pJkFgt2J$P}v*#DLPmc>)@}eht+5Mb94rrni$;rz0Mm}g5HTH(#kg=|iY7hlP z6~1I(&HD6mfLQh;fwW*4r$O_M)8kcuJH%wNRz+9TTk=}KD`}|x*Prh~M@<{{Z)N`$ zk098kwI8_H*WRVy9vrpP1?UI>gQFrMiYdd#|6TF#4Pb6`@s8oYCC9CwFg4=8g%$Um z?SJbSin(#KBmY}h*u@>n{NKtP?C$@gVT^LQeCFTk9BfjW=h5z1Si*r1;?>pF=XwA7 z{W!F^NKk;+YDvY6IQ%-@a>o`I-_bk4Kf|lrD;>0;Kz}vnbo810xqV1qf=mFW};W} zGhNJ*ei9lMzN1{!Z1%4wK+rEV#N5gAXU>!48ML$r&3~7(z9|Zq3|M=W8ZKlm=ONHd z^PHH7h)DaTT_+JS^)Sjm;}phhNO&r$fANi1nTeiyw*&vWy?V9vRQy_jAC&oiGU;!N z8S(1pGV>`)W}iCRL;nqbkb#>U<KWJ} zZ)J%zW9PYvp=mU-O`)~$^|Cqo^-UK9qH8Mi&u~^uVyqvO-b?Q%a-1`fycBy<#X_(; z@W)cP@)37Di_!ODC$9cNVrF932H$+YKCp6~f4tI|t=4wo1&|UFmXs!%>L|<+y5x38 zjqq<*@k4R1Rd_=Z+w3J>_Q@Af_10$WEO~Z{KxKb+G6|4zW#b<;Q24r)fA@{IpWnXn zpN!gC{#J1-R^O|GAO{6pNYa*=?}0F__s09y%gI;gJ4@Q8N*m&^hxwpw(~RKw<;-wv zmF^4Vl8;tdLY(R_ow?M8sI(av29r`!!oar#D_2sp>nqva1H*%|mT-X@g)66>p z%%^(}NGs|O4GjGL6EU>|ZTjB+OWbN@XVUBB;M_|1OEK5rdStyiRBVrQ}_x4p+89a_heWlGn2HNmoX zNtVaFBsIz$w4cD}3|N)YX1}Q}b~p;sS)V5})u^DCl?^W~Wq*ovGLWpi-1;JcRNq== zQnnw2(|dKEh5MrJ54nhi@Tjc(Y67Ide8?2`<@@*C%;1QK*O|4g->;w~^p}ur*Qt_3 z6e!y-lBe;s(Je=m(N(&jPg1-tW|vyt>KNkzJN}#Go(qe)m^r|R%XX;?LedUjvW#m1 zRVg7}fH%{5!=vm<;?dQvJ7rU2Er5S-7DF;f8qwvCsestkN>C0SSCe|ImYw-deAjk7 z_@WiD_R5noS4o(i|3&1zOP^HmoijopzGaUOEPfiOogV5%=%H_UDMl{HaK|I*0UWrQ{mYE-PBK6s@}H7 zCP1B|WM)%v+4Hd*VYE9CjEERmTYmSrnsc~#-sJYJjqC`woz7iLV&ZYW;&`HNHq$vSz>7@24Xmir0A6Do z?wAnei@82|V|3ML{p&WSb7AKBcuJYb>5pb&QHBR`d|Bo__e*f?D!G$>BZOES7V}mO zt})JxgUeE>+i5HIs`2}Z`*bo4PRsRfwBK?2P{MYhFdMsC*1$kiHC;6Jm^pUZUxiV6 z_cWoz^}Y_GhmlLnc{EpDK0v=eSKaoAd$BjuxrSjnFF}WeR>DU|=Uf--FM6vCjtpBM znXIm<+L$MIcu=;X<%5x$j zk=|9H9tVf;UVLweAZo4cY<`O*#<{&#rET46-8zqnYGN~fAWc0xW3*=2_@f+4_QZmv zZNtioC73rh1(XV_=BLq0@8;uLcHU!`3CjI=Z>+18r4-P>a2_Na1X!l*)O1Bn=Xuro z?PA!xuqjHnIHSRFG2fSwD(GO9QGv)$uzXyHB#Z~DNlxDY@P*=ZS}Eq0xVF~7^zK?6 zMVdjo5%_Re@jhY{lWxCXc(k$1?Vjm6342;H30M29TAY*9#I)w4k}sW77AKJ1u|u!W z77nZH%_Ug+{5WzidUV29&s2o_CVtNeOZNzQCTP=hG)#Tq)Z#QO4}n|#x%hHPT+hM0 z!C!xsU8QOTjIQ4R#ZmIRdj0IbFO6w4ZW zPNY%viqKW*k+=L6o`gFkm;X9}uNhb9ez3qb5L#VgVs7O**+_A?0tWT18Yx~eR) zakIcOB0^cG-|FM$N_&{t$zE#i>}s_n>Ea{?UCb^jmyj;Z(E!ipd$A#wrkZ@AN~wCk z+E2~>d7WL#gA4h@Gu&d`hMt*H(*Oy&SW1E4ZC;DnTve51Ka}%I03QckCnbLsx|E3j z*(BE<*F3qus)v)$byNhDuD`mzvma$)T}V>Wb|2sx+Mg{8sj*qdDO2Ps#e4Vu=pB}Q z9!g9OZ<|sd%ZJc0C?dMu=8%Ozf>%ex8gTps(K6+NghQ%fASy z?2fa**+h3p;q@825C>;)#8i`_yO30}}<^>}YK8_5U^5#@*){f@!R2 z2YdB(owsto=9VXbmV0aQ>cl&~ctUfClZ=bM+1AB`uy zlU}IG*!vJLOEsvfaC8Rr}~`m zMMl}|)y$AQifufAS80H?EgkrTxjS5{VMmM9&BQHZYw*3u4^i2R3v5+Qg1J-t?kNb1&>7t|58Kix^FD7MRR-x#^Er9T&Pt z3{XzyFijosy+pH}rzPVsu|RrRcJ0r;%YcMk!#<+|iN7n|D2 zZzAHL?TOO-L>f#Haj|kPF6vd<<4=7anf9%%bRSd?A|rOt2q#~(ZMfV@*ICN26(pJ; zdfmV=r#jN&>C|@l!U1p(m{pEgYFHuDFQmuZ4}S{3KArUC))i*4+F08ou{m-0A^1HN zZT=>UNOpPp4Q@ZPaj;3339~!jHHeY(5t-%B2 z3N>yC2obG?KZh$?b?`OFVOeh~N2eW;SD?8!1=MSw)z7T2mV8+|o*YA|o%7z8t#`u-8LKDv;v7xOWB-&>nq-SD2_w%8m6Xhx_a3)r2UqFD}n z>*N$C>f!ljMnM;u1$@IQim!J|ZYC!%@e|8PMuzYr$t5``NtG&pVjMsojhGDR_I)#PzhK;{}TuB$wp=U76Y+$*?CG9v70nL1x zrOkU#maO+9*NJ=f-3w!uWW=-9uhHBch(|^uJJy;n(B9TYWVZ8*7RQ zz_ojC7f&=kc%$rx>o>EZsn3zn(0B1=|07@>s`DV|G^ZX`CI8m=g$*$Jlw5hH1|Uck z)YO*9b{P)zyupJQ8=4h_Uix;D3B{ySlh$)ka`+w8ZG3^?-Q)~XKZv=fu@8RD?RV+s z@LHP@%3t>{zA){Wo2&7@jhr#FE?ei%M8l8#;2p_bkgHgUtFH+3p^{a?P6vS>z zW%HDaM}7HxY2x6y=jmqIzWK<&_#FyV`26Iv^7q+m--X^rXES9m(4m;v;Ff?`JdJ=Y z2wgTz+ezsnyNwk6slF+iB%eO>w)Uj`?6v!LZOhAs9x+~iMW*W7-bx^zrp5*+pyPTQ zjbyF8y$(=lkDeBW$LO7)0$tJzjU^=RqZDih=6B|&xAZ2jfNqmliAFZ-_~+VjY2;Yn!3G0HA% z3Ef-vrhY%$ICRk0n}8Kj(4|Tsqt;x#ZRlV(}h1 zC!UTF(j}8bQ)5zx#oJ`qN7~s6gYb*1^PU;4+U~3JsklabKCAiSKaHYu)y2l0?|8Hg zows74=dsR)qc(%;8-bgw=9ltDIit!_M@JdIW6&-zSa_}$zmq$7rVyJfhc~3|ZI{HR zs4Vv@x)ajW5W9a3yhCU^uQS8%n2g34>90nP81E!3)2+z;*05SHk^;nuh!SL;f=1eL zx-(52=XuQI`?!CEza1q!oH$H)HtH?}Xsq4T#3m`T4nOWZZv$ECEa} zf{Gp$O^L(ajjrI5ih~)QQp>=gZ~86b69;_|?vj%9m(XWfTdN$Q~p}v6xA*_9Pd1jRHDU8YshM# zHl>tps5_0nFH0G*uUv!}eA_eeZcpV0q-lMwa(7HK_DNOTBQA`{^%2-z56mNfJW%-I zYhcA7m@$LQk4MKV1IT?nj)FJYbV+U`H6-5+Carwc;MrN2KSBF0H9G^_7jo%iE+U9#9{fN3) z*Nty$&1GLq6F1t{?67}6F}oW#su)n3%UY-p5fh z?_NoL{x(|k^SIQ3a4aev@TqvMpP&Giuq)xfB9^gAI@HS57`3>0aeAW`o{0yvsF?Y{F32;P5Z*5}a?<*J8ih!f8D| zkexoQdZ1BPSC{ZVzD%?Kw=oKC>{cN=3soWQKZ?1ea5IFT6M#-+eamLaANw4KA9FU= z^Ex+SUAX~cU&%$PH!OSd%7}Jy(u16Z5gu->U{a(@XB>R2bUrfKgJ@=sq(qaa>6pkE zc$OM>5J_>|lR!+xWNu5f&u`7yRML`*6WL_cLSeVxT@ON44DnzWYgKlOIxBqvI-UH4 zQO72~Pqb!%2g4j9@~RM3n~3=+&p^AQI;#1n@WeBEhMdXB#d{Xe?$qV0vH*-WKhv-z z$o69~pWVG7`MBS+3}fSIE{Q9P`$G$;n=Pe@1Nwyf$qjPtXFe5q-wys;|FH3+GLe{x z$6FZh`r1=(@9t#|9OciD?n?Qk#97Mxs`HPe2E*c^G%Tk_=RY0Ausp2t$0@NOCVqC` zuz$QlC*e}@Egt9APgL{WJ3*u0st*Ls;T6Zw{QPqRqusVe(bHCRcnVWjD;AUUw(Rd# z;Ns#c*)z>;3kN7GM;Itn#Bs9g)#?TrXeqvaV;W2@=3mRCJxV;SJVd@O`Q!G_@Us}; z5uYE)jC{P40>ym^({MsP$t7z}36;;G62^H6m#WMV=_G8aO1W zR@LD8M}3mWSFM}cuEnFVo{*r9)kuZqu01})=^pdR%h`KZLae&3x{e!TqP=V`79`@E zko+Umne5>cb1Y?%>4&yE1mHs;^1N>K5D^64;NS#aV~wc<;2AzXU=l3&kwNQ#Wto#a zWJ0dT%5pOeB2qgE8kKqB60sAtg&b$~+BN)cruKIqX9PAOz=;iC2{Rpw_-drnrxp zS~}S$DiWzH#|{uPZ%Ch>$2-1-rTj$C%F%Er#J%G^LM2K#qobFMo<7XN4(6&zcz3A4cXDz&h3#JjAo{gk z@BfCWgY`@L3ni=bye9_@C570?jFQBi5WIbMUDu2;5s6s^f(QJC7F81yGvbZ{ul4UW z_bv_lSDL@-u3sc&>Y9%BXGlb=1U_JJsc|j%U8N^q?}XSwe^mtxVvnDcw|;?;Z(Wj- z$U$xAOv+=5io+BGN@6c`I7A{Mc4Q`8ev`-0sGp(PY7`Utt~O?HcWtH!dGtZNE@fRl zZEnxkwTg3ZL$|z3OEU9_4T7zvR_8V+$RFXLU)CQ}`1V>gQhs4;qG|40v2|7gyp^)7 zTDq&E7$m%zdJ?!B*f$Wm@-A%yxePyUNBok@k$))RRzjA{N^zj=JCK5aTaqXi{@gGATizBli z478oe`t{dNhWzcv2331rb&F&WvbO5__c<~}FA?AcnrezMor0ICsL1p$Z{W|L&Zy-8 z1xF)lc~db4XN8a;)Q3iow^A`J>pCRjrtTNqNGuCb2QSp$%Q|}N?rfv53lzugR3VHj z(`y((w22aituOGd~v40^; zh3fHE8P^O&MRtR~`g^BTgJbXVqhmi%$hZPq=O=3|4`<(d>gb7Wn(?gnYGUAwq5Q+j zv}x663IWy+bwKe%)l|G8u|82-=nEZb&xO;gGMFd180*gm$;7QiT9J4bZqrOgWUhI( zCrs)rK91^>XR1J8v7K@^ONCbfrrWO@JESvCp%cb579lazxeL~ZZ0T|qWX^{?N%U2U zWf7G+X6W-epWfzj%zN+^nH$3?lZjG2&7^n{r>`42(1JfT9yjnu&fmWN!U8P(ohU2d zaed53A_B-p6r0gZEU&z5sNa#pnj0%wMJ$}Kbr)M~&e&L{*av3mObK-%o{sz$9=EDO zxqZQ&*nJ6y?)1MHr7l;>vInRRC1Le0e!eU=7>VCb8F>9uoFs@d{pYcvcDOJDA2 zFk*)`jV_RuuqtGXRj2vGo$MRZ!Vj{B&XqrP&m7+UoC;ydZvi zwD`!SQ&x3HTqb?5bRFq>tRB`{Noe`@_DlMUBL&X^UC%fi{f5WZqR60pV@sJ2Aj*z4T%KGA1io z#tlMvCHpCq+?m~?ZRfPTDLme}`kbyo-gaGU#VmxWs3N1co_~yA$*J4H!2UebNJA~N zM40&Qy_6o-x+9F{g+kY_q=FCHodvCtyfSaG-ev~+D1E*E$TaS^b5fvft2?);^c&H| zrZpWmfh|Vo7qiaH0vU)ikGC1q%J{z8AK z9z_yKmJ@4C*T?A%rNMzkf=T15vo{`>Nf?Mr?4lonAaXmCh`K1%>?#`49W6zx8+e8(N8d zOMj6O88e;qVx-lWaZpKfVzk5ti3nAVbN$U9T&;4k!=3oB*_ntXVEt8Azq|#xo_=?*FwNB z5WG3p{fTnvPgh@p2WTK6W*k$A4~~=vtpw`#L%O*72LyxWPhy$qWr9A7*b7<1d5M*QuqyQ0-Nqq(jPfY~9EOo52+W!R12`=ErYVlhkEp1%g7yF(1W( zgYG%YgTyFbA;EqRNdfJ;ii3Z=XK)@fh@Tsf{sq&|8(To)Y6ixQ)W;|Lq0$|K12O~Djojb+W%X$$^TEu z1i1{7`1+rs5oZ3+cz>;hEF|Io2Kzsi|Ida-ahXxWGsyh&zhyAtuTY|WB|RcS#zoy2 z92YUb!&Bwz56`j>gRyH!pSC_rJ4=;R09?q$`DIjWBD(+pD`_zQSNBM10=bS%S|xF6 zgi?rh9$?WWjfqt;gG_}oe9v80n@*~QkcddbvrFm!r;g+QQvlMqVSm1hvlJQe8Xa?H zX1h2%c}^G{Rp7?B7hrBE-R z(G}&1M6pxj2r)?yVQMkeKbr&6k&~TgT4nt2gf;Ye{y%gl|L^e*ywL=4bg^U(4^ZJe z#6jZ!?Z>}cGBt+Y1CO}j%9&be+9rb4us)y=*5ON<_)w2(__!1m+riPP+i~g)UbYc4!k+G&k*v$gz6cK4+jG}`_rZ~R@AK1L z_b`!YZPU0eHdl&I4h}I**Tx@qwAG}_Jw|1FMO~TzQ-46}#oMx=SF`OWp}`&FIY!nf7_P(9-fV$)|k;H`M2^!Bz-;!<06rBXE1~&`Zxm>QCdK+8m8WsVe&b9 zTR#8xOHxPbxRUm}4DAVk$T^BHBHz2mIW!wN`SACs z3LE$4q2cjBk{Hp=m0|LAAEoR(K>dHYgT}>HtI|%O?%H~6)i=r2dgatToM=~XzAYf% zRczT@)Xts}R-5CcOKZZjbF8+fHkJW>+0;N+isGCSC8qOvt1+{=A1=f5-cq8wLjyia zCRj9)brtVX@Qe@#{oaiif!FqfC3^mf?XM_8-$!T2o6-S!JsI=k14tZJBgawKd3INc zo{0%RA?RpDry!Gv-JL0AXx`FIp#7aR#)0kxM)j(NkR^OC6yW0l+OUY<*aiZ0?z5Zm zOKLmRtUE(kFGRKZb!3us*mc^3p2J!e;#n}Y$Cn4dI6Nl~D{&C#!tlT=_N%c|a&8CB?o>rC)eD?6HSSxP;Cb$hFj9jLhh!4pNH}wYkh~A@sPeCNrEHEdEBx>C{cY1d~x0C%11RGFUm z(DkxjYbwGpXz%_!PA*jCx4}|Q4(pkS##0_DZn%i@+ssF!$-dkW!kh}X?4iYDiRw(f z-~|;yRQ?(E_m5_sHb-lnnAR&5ufQo1P~Ri*;}=WU2cL5wj7a}1rZ4^zhb1xb5VcC) z^AgI_NoIcVc>ihMxI&r@PNW)_7T5A1M9TMoM6VO0CDkl$`UK|eY5BTOps%rXZ7dqv z4Pu|)b&dh;QL^Mm4PqKYq8q#K>J+lW8UBC)J+Xj(&owYc?4gkblAHC?cu$a>!YU zXdP?AdxuRcQm#xtVv|Rj98?1Abtep8Fmf-+VpAn|J8&x4a;4b#EDD(Fv6z845R!;L zvjnnbgxs#j*{fq1Pq;na(2BUL+HxHr&{nrGrYAmUwzPjKmUuk$zFRLM55Z{MK9mWz z#mYJgc;U{2O$Qc7ZM(bpdn=F?NIrwP@*f0amhWV7v4^`-cH}pn^tC^e;k~TT3l|`o zTi)zJ~hvx)vyd=)V5N(n;SDsTL z)+&9w_j8`S6aldZ1;5RO2qa(@JVCL}lQw-Yn*MawYIn1?!ugAa1I4cm{!%ME+ z;@gMKoV2qIFsap}@zNckpo7G-h)Gp=#>xCLl9K5KvbrZUcsia)LfsAA53+V&~GxBnYV&-R}bXOSJ=0zLYzQ6P*MuM55-|3A96T%1YkuYG1`mD*O*u$EQdy)A&d! zg}r{1Y!$<<=YRBW)-D7~t$ zPaBaY&F`dQuQJzWvg3^}FApAknRQ5P^((2|m&HQN5x!pMyA=jz3-lc7OxL`LN!8mP z=YuK9jWt?J7wQn7F_{l{v!b8)akNcqX?~vy)ORu@#PK0ic9g*7