diff --git a/cmake/riscv32-unknown-elf.cmake b/cmake/riscv32-unknown-elf.cmake new file mode 100644 index 000000000..cfd9f7eae --- /dev/null +++ b/cmake/riscv32-unknown-elf.cmake @@ -0,0 +1,29 @@ +# Toolchain settings +set(CMAKE_C_COMPILER riscv32-unknown-elf-gcc) +set(CMAKE_CXX_COMPILER riscv32-unknown-elf-g++) +set(AS riscv32-unknown-elf-as) +set(AR riscv32-unknown-elf-ar) +set(OBJCOPY riscv32-unknown-elf-objcopy) +set(OBJDUMP riscv32-unknown-elf-objdump) +set(SIZE riscv32-unknown-elf-size) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# this makes the test compiles use static library option so that we don't need to pre-set linker flags and scripts +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +set(CMAKE_C_FLAGS "${CFLAGS}" CACHE INTERNAL "c compiler flags") +set(CMAKE_CXX_FLAGS "${CXXFLAGS}" CACHE INTERNAL "cxx compiler flags") +set(CMAKE_ASM_FLAGS "${ASFLAGS} -D__ASSEMBLER__ -D__riscv_float_abi_single" CACHE INTERNAL "asm compiler flags") +set(CMAKE_EXE_LINKER_FLAGS "${LDFLAGS}" CACHE INTERNAL "exe link flags") + +SET(CMAKE_C_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "c debug compiler flags") +SET(CMAKE_CXX_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "cxx debug compiler flags") +SET(CMAKE_ASM_FLAGS_DEBUG "-g -ggdb3" CACHE INTERNAL "asm debug compiler flags") + +SET(CMAKE_C_FLAGS_RELEASE "-O3" CACHE INTERNAL "c release compiler flags") +SET(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE INTERNAL "cxx release compiler flags") +SET(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release compiler flags") diff --git a/cmake/riscv32_gnu.cmake b/cmake/riscv32_gnu.cmake new file mode 100644 index 000000000..617b12760 --- /dev/null +++ b/cmake/riscv32_gnu.cmake @@ -0,0 +1,12 @@ +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR risc-v32) + +set(THREADX_ARCH "risc-v32") +set(THREADX_TOOLCHAIN "gnu") +set(ARCH_FLAGS "-g -march=rv32gc -mabi=ilp32d -mcmodel=medany") +set(CFLAGS "${ARCH_FLAGS}") +set(ASFLAGS "${ARCH_FLAGS}") +set(LDFLAGS "${ARCH_FLAGS}") + +include(${CMAKE_CURRENT_LIST_DIR}/riscv32-unknown-elf.cmake) diff --git a/ports/risc-v32/gnu/CMakeLists.txt b/ports/risc-v32/gnu/CMakeLists.txt new file mode 100644 index 000000000..9357c6970 --- /dev/null +++ b/ports/risc-v32/gnu/CMakeLists.txt @@ -0,0 +1,19 @@ + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/CMakeLists.txt b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/CMakeLists.txt new file mode 100644 index 000000000..0d8c22eac --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.15 FATAL_ERROR) + +project(demo_threadx + LANGUAGES C ASM +) + +set(SRCS + ${CMAKE_CURRENT_LIST_DIR}/demo_threadx.c + ${CMAKE_CURRENT_LIST_DIR}/pre_main.c + ${CMAKE_CURRENT_LIST_DIR}/boards/board_riscv_dummy/src/uart/board_uart.c + ${CMAKE_CURRENT_LIST_DIR}/boards/board_riscv_dummy/src/board_init.c + ${CMAKE_CURRENT_LIST_DIR}/components/csi/csi2/src/csi_misc.c + ${CMAKE_CURRENT_LIST_DIR}/components/libc_threadx/mini_printf.c + ${CMAKE_CURRENT_LIST_DIR}/components/libc_threadx/newlib_stub.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/arch/e906fdp/startup.S + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/arch/e906fdp/vectors.S + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/arch/e906fdp/system.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/arch/e906fdp/trap_c.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/drivers/dw_uart_ll.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/drivers/uart.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/sys/devices.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/sys/feature.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/sys/irq_port.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/sys/irq.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/sys/pre_main.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/sys/sys_clk.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/sys/target_get.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/sys/tick.c + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/src/sys/weak.c +) + +include_directories( + ${CMAKE_CURRENT_LIST_DIR}/../../../../../common/inc + ${CMAKE_CURRENT_LIST_DIR}/../../inc + ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/boards/board_riscv_dummy/include + ${CMAKE_CURRENT_LIST_DIR}/components/csi/csi2/include + ${CMAKE_CURRENT_LIST_DIR}/components/libc_threadx/include + ${CMAKE_CURRENT_LIST_DIR}/components/libc_threadx/compilers/gcc + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/include + ${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/include/asm +) + +add_compile_options( + -Os -g -Wno-main + -Wpointer-arith -Wno-undef -ffunction-sections -fdata-sections -fno-inline-functions -fno-builtin -fno-strict-aliasing + -DCONFIG_SUPPORT_TSPEND=1 + -DCONFIG_ARCH_MAINSTACK=4096 + -DCONFIG_ARCH_INTERRUPTSTACK=4096 + -DCONFIG_SUPPORT_IRQ_NESTED=1 + -DCONFIG_INTC_CLIC=1 + -DCONFIG_INTC_CLINT=1 + -DCONFIG_XIP=1 + -DCONFIG_LIBC_MINI_PRINTF_SUPPORT=1 + -DCONFIG_SYSTICK_HZ=100 + -DCONFIG_BOARD_SMARTL_EVB=1 + -DCONFIG_CPU_XUANTIE_E906FDP=1 + -DCONFIG_KERNEL_THREADX=1 + -DTX_INCLUDE_USER_DEFINE_FILE +) + +add_link_options( + -nostartfiles -Wl,--gc-sections + -T${CMAKE_CURRENT_LIST_DIR}/components/chip_riscv_dummy/gcc_flash_smartl.ld + -Wl,-zmax-page-size=1024 + -Wl,-Map=${PROJECT_NAME}.map +) + +link_directories(${CMAKE_CURRENT_LIST_DIR}/../../../../../build) +add_executable(${PROJECT_NAME} ${SRCS}) +set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}.elf") +target_link_libraries(${PROJECT_NAME} PRIVATE threadx) + +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${OBJDUMP} -d $ > ${PROJECT_NAME}.asm + COMMENT "Generating ASM disassembly files" +) \ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/include/board.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/include/board.h new file mode 100644 index 000000000..a0f81d7aa --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/include/board.h @@ -0,0 +1,444 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 Component, New Board should follow 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 described 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 means No uart support. + the BOARD_UART_XXX, x in range 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 + +#define EXAMPLE_TIMER_IDX 0 + +/****************************************************************************/ +// 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__ */ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/include/csi_config.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/include/csi_config.h new file mode 100644 index 000000000..8e1af58fa --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/include/csi_config.h @@ -0,0 +1,26 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_CONFIG_H__ +#define __CSI_CONFIG_H__ + + + + + +#endif /* __CSI_CONFIG_H__ */ \ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/src/board_init.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/src/board_init.c new file mode 100644 index 000000000..b994f6ce9 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/src/board_init.c @@ -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. + */ + +#include +#include +#include + +void board_init(void) +{ + /* some board preconfig */ + // board_xxx(); + +#if defined(BOARD_GPIO_PIN_NUM) && BOARD_GPIO_PIN_NUM > 0 + board_gpio_pin_init(); +#endif + +#if defined(BOARD_UART_NUM) && BOARD_UART_NUM > 0 +#if !defined(RT_DEBUG_INIT) || !RT_DEBUG_INIT + board_uart_init(); +#endif +#endif + +#if defined(BOARD_PWM_NUM) && BOARD_PWM_NUM > 0 + board_pwm_init(); +#endif + +#if defined(BOARD_ADC_NUM) && BOARD_ADC_NUM > 0 + board_adc_init(); +#endif + +#if defined(BOARD_BUTTON_NUM) && BOARD_BUTTON_NUM > 0 + board_button_init(); +#endif + +#if defined(BOARD_LED_NUM) && BOARD_LED_NUM > 0 + board_led_init(); +#endif + +#if defined(BOARD_WIFI_SUPPORT) && BOARD_WIFI_SUPPORT > 0 + board_wifi_init(); +#endif + +#if defined(BOARD_BT_SUPPORT) && BOARD_BT_SUPPORT > 0 + board_bt_init(); +#endif + +#if defined(BOARD_AUDIO_SUPPORT) && BOARD_AUDIO_SUPPORT > 0 + board_audio_init(); +#endif +} + +#ifdef CONFIG_KERNEL_THREADX +#include + +extern unsigned long g_heap_start; +extern unsigned long g_heap_end; + +TX_BYTE_POOL tx_byte_pool_0; +UCHAR *tx_memory_area; + +void tx_mem_pool_init(void) +{ + ULONG pool_size = g_heap_end - g_heap_start; + tx_memory_area = (UCHAR *)g_heap_start; + + tx_byte_pool_create(&tx_byte_pool_0, "byte pool sys 0", tx_memory_area, pool_size); +} +#endif diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/src/uart/board_uart.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/src/uart/board_uart.c new file mode 100644 index 000000000..315e3aedb --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/boards/board_riscv_dummy/src/uart/board_uart.c @@ -0,0 +1,45 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#if CONFIG_DEVICES_RVM_HAL +#include +#else +#include +#endif + +#if CONFIG_DEVICES_RVM_HAL +void board_uart_init(void) +{ + rvm_uart_drv_register(0); +} +#else +__attribute__((weak)) csi_uart_t g_console_handle; + +void board_uart_init(void) +{ + /* init the console */ + csi_uart_init(&g_console_handle, CONSOLE_UART_IDX); + + /* config the UART */ + csi_uart_baud(&g_console_handle, CONFIG_CLI_USART_BAUD); + csi_uart_format(&g_console_handle, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_BITS_1); +} +#endif diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_libthreadx.sh b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_libthreadx.sh new file mode 100755 index 000000000..ff9bb9306 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_libthreadx.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +pushd ../../../../../ +rm -rf build +cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/xuantie_e906_gnu.cmake . +cmake --build ./build/ +popd diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_threadx_sample.sh b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_threadx_sample.sh new file mode 100755 index 000000000..ec91e36a5 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_threadx_sample.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +bash build_libthreadx.sh + +rm -rf build +cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=xuantie_e906_gnu.cmake . +cmake --build ./build/ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/gcc_flash_smartl.ld b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/gcc_flash_smartl.ld new file mode 100644 index 000000000..3cfad67d4 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/gcc_flash_smartl.ld @@ -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. + */ + +/****************************************************************************** + * @file gcc_csky.ld + * @brief csky linker file + * @version V1.0 + * @date 02. June 2017 + ******************************************************************************/ +MEMORY +{ + ISRAM : ORIGIN = 0x00000000 , LENGTH = 0x30000 /* ISRAM 192KB*/ + DSRAM : ORIGIN = 0x20000000 , LENGTH = 0xC0000 /* DSRAM 768KB*/ + SRAM : ORIGIN = 0x60000000 , LENGTH = 0x20000 /* SRAM 128KB, no cacheable*/ +} + +__min_heap_size = 0x200; +PROVIDE (__ram_end = 0x200C0000); +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(*whetstone.o(*.text)) + KEEP(*startup.S.obj(*.text)) + KEEP(*startup.S.obj(*.vectors)) + KEEP(*vectors.S.obj(*.text)) + KEEP(*whetstone.c.obj(*.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 + .eh_frame_hdr : { + *(.eh_frame_hdr) + } > REGION_TEXT + .eh_frame : ONLY_IF_RO { + KEEP (*(.eh_frame)) + } > 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) ; + __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(0x20) { + __sbss = . ; + __bss_start__ = . ; + KEEP(*linpack.o(*.bss*)) + *(.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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/asm/riscv_asm_macro.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/asm/riscv_asm_macro.h new file mode 100644 index 000000000..dfa085788 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/asm/riscv_asm_macro.h @@ -0,0 +1,538 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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__ + + +#include "riscv_csr.h" + +.macro RESTORE_xSTATUS + /* 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 t1, sp, t1 + + /* now, t1 is the position of mstatus */ + load_x t3, (0)(t1) + csrw MODE_PREFIX(status), t3 +.endm + +.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 + +.macro RESTORE_SYS_GP + .option push + .option norelax + la gp, __global_pointer$ + .option pop +.endm + +#endif /* __RISCV_ASM_MACRO_H__ */ + diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/asm/riscv_csr.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/asm/riscv_csr.h new file mode 100644 index 000000000..0bea1b57a --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/asm/riscv_csr.h @@ -0,0 +1,191 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 store_x sd + #define load_x ld + #define portWORD_SIZE 8 +#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 + #define portFPU_REG_SIZE 8 +#elif __riscv_flen == 32 + #define fstore_x fsw + #define fload_x flw + #define portFPU_REG_SIZE 4 +#endif + +#if 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 \ + || CONFIG_CPU_XUANTIE_C920 +#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 \ + || CONFIG_CPU_XUANTIE_C910 || CONFIG_CPU_XUANTIE_C920 +#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_C908_V2 || CONFIG_CPU_XUANTIE_C908V_V2 || CONFIG_CPU_XUANTIE_C908I_V2 \ + || CONFIG_CPU_XUANTIE_C908_CP_V2 || CONFIG_CPU_XUANTIE_C908V_CP_V2 || CONFIG_CPU_XUANTIE_C908I_CP_V2 \ + || CONFIG_CPU_XUANTIE_C908_CP_XT_V2 || CONFIG_CPU_XUANTIE_C908V_CP_XT_V2 || CONFIG_CPU_XUANTIE_C908I_CP_XT_V2 \ + || CONFIG_CPU_XUANTIE_C908VK_CP_V2 || CONFIG_CPU_XUANTIE_C908VK_CP_XT_V2 \ + || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920 \ + || CONFIG_CPU_XUANTIE_C910 || CONFIG_CPU_XUANTIE_C920 \ + || CONFIG_CPU_XUANTIE_XT_C930_CP || CONFIG_CPU_XUANTIE_XT_C930V_CP +#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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/drv/dev_tag.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/drv/dev_tag.h new file mode 100644 index 000000000..4e7590c4b --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/drv/dev_tag.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/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_AHB_DMA_TAG, + DEV_DW_AXI_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, + DEV_XT_IOPMP_TAG, +} csi_dev_tag_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_TAG_H_ */ + diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/dw_timer_ll.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/dw_timer_ll.h new file mode 100644 index 000000000..cb7bf1083 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/dw_uart.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/dw_uart.h new file mode 100644 index 000000000..e69de29bb diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/dw_uart_ll.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/dw_uart_ll.h new file mode 100644 index 000000000..50a7de0b9 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/dw_uart_ll.h @@ -0,0 +1,423 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +/*! 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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/soc.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/soc.h new file mode 100644 index 000000000..e77cb3057 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/soc.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. + */ + +#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 + +#if __riscv_xlen == 32 +#define INVALID_ADDRESS 0xFFFFFFFFU +#elif __riscv_xlen == 64 +#define INVALID_ADDRESS 0xFFFFFFFFFFFFFFFFULL +#else +#error "Unsupported RISC-V XLEN." +#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; + +#define CONFIG_IRQ_NUM 64U +#if CONFIG_INTC_CLIC_PLIC +#undef CONFIG_IRQ_NUM +#define CONFIG_IRQ_NUM (64U + PLIC_IRQ_OFFSET) +#endif + +#if CONFIG_INTC_CLIC_APLIC +#undef CONFIG_IRQ_NUM +#define CONFIG_IRQ_NUM (64U + APLIC_IRQ_OFFSET) +#endif + +#if CONFIG_INTC_IMSIC_APLIC +#undef CONFIG_IRQ_NUM +#define CONFIG_IRQ_NUM (IMSIC_MAX_INTERRUPTS) +#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; + +#if CONFIG_BOARD_SMARTM_EVB +#define DW_UART0_BASE 0x180000UL +#define DW_TIMER0_BASE 0x181000UL +#define DW_TIMER1_BASE 0x181014UL +#define DW_TIMER2_BASE 0x181028UL +#define DW_TIMER3_BASE 0x18103CUL + +#else + +#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 +#endif /* CONFIG_BOARD_SMARTM_EVB */ + +#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_DMA0_IRQn = 17U, /* dma0 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 */ + IOPMP0_IRQn = 32U, /* iopmp0 Interrupt */ + END_IRQn = 1024U + PLIC_IRQ_OFFSET +} irqn_type_t; +#elif CONFIG_INTC_CLIC_APLIC +typedef enum IRQn { + L2_CACHE_ECC_IRQn = 1U + APLIC_IRQ_OFFSET, /* l2 cache ecc Interrupt */ + + DW_DMA0_IRQn = 17U, /* dma0 Interrupt */ + DW_UART0_IRQn = 20U + APLIC_IRQ_OFFSET, /* uart Interrupt */ + TIM0_IRQn = 25U, /* timer0 Interrupt for CLIC*/ + TIM1_IRQn = 26U, /* timer1 Interrupt for CLIC*/ + TIM2_IRQn = 27U + APLIC_IRQ_OFFSET, /* timer2 Interrupt */ + TIM3_IRQn = 28U + APLIC_IRQ_OFFSET, /* timer3 Interrupt */ + IOPMP0_IRQn = 32U, /* iopmp0 Interrupt */ + END_IRQn = 1024U + APLIC_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_DMA0_IRQn = 17U, /* dma0 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 */ + IOPMP0_IRQn = 32U, /* iopmp0 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) +#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 + +///////////////////////////////////////////////// +#define DW_DMA0_BASE (0x18000000UL) +#define XT_IOPMP0_BASE (0x26f00000UL) + +#define CONFIG_AXI_DMA_CHANNEL_NUM 8U +#define CONFIG_AXI_DMA_FIFO_SIZE 0x8U +#define CONFIG_AXI_DMA_BLK_MAX_SIZE 0x3FFFFFU + +// #define CONFIG_AHB_DMA_CHANNEL_NUM 8U +// #define CONFIG_AHB_DMA_FIFO_SIZE 0x8U +// #define CONFIG_AHB_DMA_BLK_MAX_SIZE 0xFFFU +///////////////////////////////////////////////// + +#else +#error "Not support soc!!!" +#endif /* CONFIG_BOARD_XIAOHUI_EVB */ + +#endif /* end exx*/ + +#if CONFIG_INTC_CLIC && CONFIG_INTC_PLIC +#error "CONFIG_INTC_CLIC and CONFIG_INTC_PLIC cannot coexist" +#endif + +#if CONFIG_INTC_CLIC && CONFIG_INTC_APLIC +#error "CONFIG_INTC_CLIC and CONFIG_INTC_APLIC cannot coexist" +#endif + +#if CONFIG_INTC_PLIC && CONFIG_INTC_APLIC +#error "CONFIG_INTC_PLIC and CONFIG_INTC_APLIC cannot coexist" +#endif + +#if CONFIG_INTC_CLIC && CONFIG_INTC_CLIC_PLIC +#error "CONFIG_INTC_CLIC and CONFIG_INTC_CLIC_PLIC cannot coexist" +#endif + +#if CONFIG_INTC_CLIC && CONFIG_INTC_CLIC_APLIC +#error "CONFIG_INTC_CLIC and CONFIG_INTC_CLIC_APLIC cannot coexist" +#endif + +#if CONFIG_INTC_CLIC_PLIC && CONFIG_INTC_CLIC_APLIC +#error "CONFIG_INTC_CLIC_PLIC and CONFIG_INTC_CLIC_APLIC cannot coexist" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _SOC_H_ */ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/sys_clk.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/sys_clk.h new file mode 100644 index 000000000..3d74f5e9a --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/arch/e906fdp/startup.S b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/arch/e906fdp/startup.S new file mode 100644 index 000000000..2c6f8c3e4 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/arch/e906fdp/startup.S @@ -0,0 +1,224 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +#if !CONFIG_SUPPORT_NON_VECTOR_IRQ +.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 +#else /* CONFIG_SUPPORT_NON_VECTOR_IRQ */ +.section .vectors, "aw", @progbits + .align 6 + .globl __Vectors + .type __Vectors, @object +__Vectors: + .long do_irq + .long do_irq + .long do_irq + .long tspend_handler + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + + /* External interrupts */ + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq + .long do_irq +#endif /* CONFIG_SUPPORT_NON_VECTOR_IRQ */ + + .size __Vectors, . - __Vectors + + .text + .align 2 + j Reset_Handler + .align 2 + .long 0x594B5343 /* CSKY ASCII */ + .long 0x594B5343 /* CSKY ASCII */ + .align 2 +_start: + .text + .align 2 + .global Reset_Handler + .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, "aw", @nobits + .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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/arch/e906fdp/system.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/arch/e906fdp/system.c new file mode 100644 index 000000000..468eeda38 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/arch/e906fdp/system.c @@ -0,0 +1,119 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "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; +#if !CONFIG_SUPPORT_NON_VECTOR_IRQ + CLIC->CLICINT[i].ATTR = 1; /* use vector interrupt */ +#else + CLIC->CLICINT[i].ATTR = 0; /* use non-vector interrupt */ +#endif + csi_vic_set_prio(i, 3); + } + /* tspend use vector&positive interrupt */ + CLIC->CLICINT[Machine_Software_IRQn].ATTR = 0x3; + csi_vic_set_prio(Machine_Software_IRQn, 1); + 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) +{ + extern int cpu_features_init(void); + cpu_features_init(); + + /* 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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/arch/e906fdp/trap_c.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/arch/e906fdp/trap_c.c new file mode 100644 index 000000000..f36e86b25 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/arch/e906fdp/vectors.S b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/arch/e906fdp/vectors.S new file mode 100644 index 000000000..20840bc50 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/arch/e906fdp/vectors.S @@ -0,0 +1,900 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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" + +#define RISCV_MCAUSE_IRQ_POS 31 + +.section .stack, "aw", @nobits + .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 + .align 2 + irq_nested_level: + .long 0 + + irq_nested_mcause: + .long 0, 0, 0, 0, 0, 0 +#endif + +/* for interrupt tail-chaining debug */ +#if CONFIG_DEBUG_TAIL_CHAINING +.global g_irq_tailchain_loops +g_irq_tailchain_loops: +.long 0 +#endif + +.text + +#if !CONFIG_SUPPORT_IRQ_NESTED + .align 2 + .weak Default_IRQHandler + .type Default_IRQHandler, %function +Default_IRQHandler: +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -4 + sw s0, (sp) +#endif + + csrw mscratch, sp + la sp, g_top_irqstack + addi sp, sp, -76 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + csrr t1, mstatus + sw t1, 72(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) + 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 + mv t3, t1 +#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) + + RESTORE_xSTATUS + + 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) + + addi sp, sp, 76 + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 4 +#endif + mret +#else /* CONFIG_SUPPORT_IRQ_NESTED */ + .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 + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sw s0, (sp) + csrr t0, mepc + sw t0, 4(sp) +#endif + + 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, -76 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + csrr t1, mstatus + sw t1, 72(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) + 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 + mv t3, t1 +#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 + + RESTORE_xSTATUS + + 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) + + addi sp, sp, 76 + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + 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 + + RESTORE_xSTATUS + + 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) + + addi sp, sp, 76 + mret +#endif /* CONFIG_SUPPORT_IRQ_NESTED */ + +/****************************************************************************** + * 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 + +/******************************************************************************* + * Functions: + * void Default_Handler(void); + * Non-Vector Interrupt Handler,Exception Handler,NMI Handler + ******************************************************************************/ +#if !CONFIG_SUPPORT_IRQ_NESTED + .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 + + srli t1, t0, RISCV_MCAUSE_IRQ_POS + bnez t1, is_interrupt + + 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 + +is_interrupt: + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -4 + sw s0, (sp) +#endif + csrw mscratch, sp + la sp, g_top_irqstack + addi sp, sp, -76 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + csrr t1, mstatus + sw t1, 72(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) + 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 + mv t3, t1 +#endif + SAVE_FLOAT_REGISTERS + +#if CONFIG_DEBUG_TAIL_CHAINING + li t2, 0 + la t1, g_irq_tailchain_loops + sw t2, 0(t1) +#endif + + csrrci t0, mnxti, MSTATUS_MIE + beqz t0, irq_done + +irq_loop: +#if CONFIG_DEBUG_TAIL_CHAINING + la t2, g_irq_tailchain_loops + lw t1, 0(t2) + addi t1, t1, 1 + sw t1, 0(t2) +#endif + lw t1, 0(t0) + jalr t1 + csrrci t0, mnxti, MSTATUS_MIE + bnez t0, irq_loop + +irq_done: + RESTORE_xSTATUS + + RESTORE_FLOAT_REGISTERS + +#if __riscv_dsp + lw t0, 0(sp) + csrw vxsat, t0 + addi sp, sp, 4 +#endif /*__riscv_dsp */ + + lw a1, 64(sp) + csrw mcause, a1 + + 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) + + addi sp, sp, 76 + csrr sp, mscratch + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 4 +#endif + mret + +#else /* CONFIG_SUPPORT_IRQ_NESTED */ + + .align 6 + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + addi sp, sp, -8 + sw t0, 0x0(sp) + sw t1, 0x4(sp) + + csrr t0, mcause + + /* Check is interrupt */ + srli t1, t0, RISCV_MCAUSE_IRQ_POS + bnez t1, is_interrupt + + /* Check for nmi */ + andi t0, t0, 0x3FF + li t1, 24 + beq t0, t1, .NMI_Handler + + lw t0, 0x0(sp) + lw t1, 0x4(sp) + addi sp, sp, 8 + + /* is exception */ + j trap + +is_interrupt: + 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, trap + + 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, .Nested_Context + +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, -8 + sw s0, (sp) + csrr t0, mepc + sw t0, 4(sp) +#endif + + csrw mscratch, sp + la sp, g_top_irqstack + j .Save_Context + +.Nested_Context: + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 +.Save_Context: + addi sp, sp, -76 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + csrr t1, mstatus + sw t1, 72(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) + 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 + mv t3, t1 +#endif + SAVE_FLOAT_REGISTERS + + csrrci t0, mnxti, MSTATUS_MIE + csrs mstatus, 8 /* enable irq for preemption */ + lw t1, 0(t0) /* Get handler from vector table */ + jalr t1 /* Call handler */ + + csrc mstatus, 8 /* disable irq for critical section */ + + /* 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) + + la t0, irq_nested_level + lw t1, (t0) + addi t1, t1, -1 + sw t1, (t0) + bgt t1, zero, .Nested_Return + + RESTORE_xSTATUS + + 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) + + addi sp, sp, 76 + csrr sp, mscratch +#if CONFIG_PROFILING_PERF && CONFIG_PERF_BACKTRACE_USE_FP + addi sp, sp, 8 +#endif + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 8 + mret + +.Nested_Return: + /* 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 + + RESTORE_xSTATUS + + 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) + + addi sp, sp, 76 + mret +#endif /* CONFIG_SUPPORT_IRQ_NESTED */ +.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, -76 + sw t0, 4(sp) + sw t1, 8(sp) + csrr t0, mepc + csrr t1, mcause + sw t1, 64(sp) + sw t0, 68(sp) + csrr t1, mstatus + sw t1, 72(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) + 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 + mv t3, t1 +#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) + + RESTORE_xSTATUS + + 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 t0, 72(sp) + csrw 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) + + addi sp, sp, 76 + 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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/drivers/dw_uart_ll.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/drivers/dw_uart_ll.c new file mode 100644 index 000000000..15ae00beb --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/drivers/uart.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/drivers/uart.c new file mode 100644 index 000000000..5f335b4da --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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)); +} + +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); + } +} + +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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/devices.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/devices.c new file mode 100644 index 000000000..48011f2af --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/devices.c @@ -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. + */ + +#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 +#if defined(DW_DMA0_BASE) + {DW_DMA0_BASE, DW_DMA0_IRQn, 0, DEV_DW_AHB_DMA_TAG}, + {DW_DMA0_BASE, DW_DMA0_IRQn, 0, DEV_DW_AXI_DMA_TAG}, +#endif +#if defined(XT_IOPMP0_BASE) + {XT_IOPMP0_BASE, IOPMP0_IRQn, 0, DEV_XT_IOPMP_TAG}, +#endif + {0, 0, 0, 0} +}; + +const csi_dma_ch_info_t g_dma_chnum[] = { + {0, 8}, + {DEV_IDX_INVALID, 0}, +}; + +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} +}; + +const csi_dma_handshake_ctrl_t xs0_dma0_handshake_ctrl_list[] = { + {DEV_IDX_INVALID, DEV_BLANK_TAG, 0xFFU, 0xFFU}, +}; + +const csi_dma_handshake_list_t g_handshake_list[] = { + {0, xs0_dma0_handshake_ctrl_list}, + {DEV_IDX_INVALID, NULL}, +}; diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/feature.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/feature.c new file mode 100644 index 000000000..018011df2 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/feature.c @@ -0,0 +1,311 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +// I/D Cache will enable in cache_init +void cpu_features_init(void) +{ +#if CONFIG_CPU_XUANTIE_E901PLUS_CP || CONFIG_CPU_XUANTIE_E901PLUS_B_CP || CONFIG_CPU_XUANTIE_E901PLUS_M_CP || CONFIG_CPU_XUANTIE_E901PLUS_BM_CP + return; +#endif + +#if CONFIG_CPU_XUANTIE_E901_CP || CONFIG_CPU_XUANTIE_E901_B_CP || CONFIG_CPU_XUANTIE_E901_ZM_CP || CONFIG_CPU_XUANTIE_E901_BZM_CP + return; +#endif + +#if CONFIG_CPU_XUANTIE_E902 || CONFIG_CPU_XUANTIE_E902M + return; +#endif + +#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 + rv_csr_write(CSR_MXSTATUS, 0x440800); + rv_csr_write(CSR_MHCR, 0x103f & (~0x3)); + return; +#endif + +#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 + rv_csr_write(CSR_MXSTATUS, 0x440800); + rv_csr_write(CSR_MHINT, 0x600c); + rv_csr_write(CSR_MHCR, 0x103f & (~0x3)); + return; +#endif + + volatile unsigned int i, cpu_type, cpu_ver, cpu_tnmodel; + unsigned long version[8]; + + /* As CPUID is a fifo register, try to find + * the CPUID[0] whose index(bit[31:28]) == 0 */ + for (i = 0; i < 8; i++) { + version[0] = rv_csr_read(CSR_MCPUID); + if (((version[0]&0xf0000000) >> 28) == 0) + break; + } + + for (i = 1; i < 8; i++) + version[i] = rv_csr_read(CSR_MCPUID); + + cpu_type = (version[0] >> 18) & 0xf; + cpu_tnmodel = (version[0] >> 14) & 0x1; + cpu_ver = (version[1] >> 12) & 0xffff; + + rv_csr_write(CSR_MCOR, 0x70013); + + /* + * Warning: CSR_MCCR2 contains an L2 cache latency setting, + * you need to confirm it by your own soc design. + */ + switch (cpu_type) { + case 0x1: + if (cpu_ver >= 0x0) { + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe249000b); + rv_csr_write(CSR_MXSTATUS, 0x638000); + rv_csr_write(CSR_MHINT, 0x1ee30c); + rv_csr_write(CSR_MHCR, 0x11ff & (~0x3)); + rv_csr_write(CSR_MHINT2,0x180); + } else { + while(1); + } + break; + case 0x2: + if (cpu_ver >= 0x0) { + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xa042000a); + rv_csr_write(CSR_MXSTATUS, 0x438100); + rv_csr_write(CSR_MHINT, 0x21aa10c); + rv_csr_write(CSR_MHCR, 0x10011ff & (~0x3)); + rv_csr_write(CSR_MHINT4, 0x10000080); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else { + while(1); + } + break; + case 0x3: + if (cpu_ver >= 0x1080 && cpu_ver <= 0x10bf) { //1.2.0~1.2.x + rv_csr_write(CSR_MCCR2, 0xe0010009); + rv_csr_write(CSR_MXSTATUS, 0x638000); + rv_csr_write(CSR_MHINT, 0x6e30c); + rv_csr_write(CSR_MHCR, 0x1ff & (~0x3)); + } else if (cpu_ver == 0x10ca) { //1.3.10 + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe2490009); + rv_csr_write(CSR_MXSTATUS, 0x638000); + rv_csr_write(CSR_MHINT, 0x66e30c); + rv_csr_write(CSR_MHCR, 0x17f & (~0x3)); + rv_csr_write(CSR_MHINT2, 0x420000); + rv_csr_write(CSR_MHINT4, 0x410); + } else if (cpu_ver >= 0x1100 && cpu_ver <= 0x113f) { //1.4.0~1.4.x + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe2490009); + rv_csr_write(CSR_MXSTATUS, 0x638000); + rv_csr_write(CSR_MHINT, 0x16e30c); + rv_csr_write(CSR_MHCR, 0x1ff & (~0x3)); + } else if (cpu_ver >= 0x1140 && cpu_ver <= 0x117f) { //1.5.0~1.5.x + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe2490009); + rv_csr_write(CSR_MXSTATUS, 0x638000); + rv_csr_write(CSR_MHINT, 0xe6e30c); + rv_csr_write(CSR_MHINT2, 0x180); + rv_csr_write(CSR_MHCR, 0x1ff & (~0x3)); + } else if (cpu_ver >= 0x1180 && cpu_ver <= 0x1183) { //1.6.0~1.6.3 + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe249000b); + rv_csr_write(CSR_MXSTATUS, 0x638000); + rv_csr_write(CSR_MHINT, 0x1ee30c); + rv_csr_write(CSR_MHINT2, 0x180); + rv_csr_write(CSR_MHCR, 0x1ff & (~0x3)); + } else if (cpu_ver >= 0x1184 && cpu_ver <= 0x123f) { //1.6.4~1.8.x + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe249000b); + rv_csr_write(CSR_MXSTATUS, 0x638000); + rv_csr_write(CSR_MHINT, 0x1ee30c); + rv_csr_write(CSR_MHINT2, 0x180); + rv_csr_write(CSR_MHCR, 0x11ff & (~0x3)); + } else if (cpu_ver >= 0x2000 && cpu_ver <= 0x200e) { //2.0.0~2.0.14 + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe249000b); + rv_csr_write(CSR_MXSTATUS, 0x438000); + rv_csr_write(CSR_MHINT, 0x31ea32c); + rv_csr_write(CSR_MHINT2, 0x180); + rv_csr_write(CSR_MHCR, 0x11ff & (~0x3)); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else if (cpu_ver >= 0x200f && cpu_ver <= 0x2045) { //2.0.15~2.1.5 + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe249000b); + rv_csr_write(CSR_MXSTATUS, 0x438000); + rv_csr_write(CSR_MHINT, 0x11ea32c); + rv_csr_write(CSR_MHINT2, 0x180); + rv_csr_write(CSR_MHCR, 0x11ff & (~0x3)); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else if (cpu_ver >= 0x2046 && cpu_ver <= 0x20c3) { //2.1.6~2.3.3 + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe249000b); + rv_csr_write(CSR_MXSTATUS, 0x438000); + rv_csr_write(CSR_MHINT, 0x31ea32c); + rv_csr_write(CSR_MHINT2, 0x180); + rv_csr_write(CSR_MHCR, 0x11ff & (~0x3)); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else if (cpu_ver >= 0x20c4 && cpu_ver <= 0x2fff) { //2.3.4~2.x.x + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe249000b); + rv_csr_write(CSR_MXSTATUS, 0x438100); + rv_csr_write(CSR_MHINT, 0x31ea32c); + rv_csr_write(CSR_MHINT2, 0x180); + rv_csr_write(CSR_MHCR, 0x11ff & (~0x3)); + rv_csr_write(CSR_MHINT4, 0x2080); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else if (cpu_ver >= 0x3000 && cpu_ver <= 0x3fff) { //3.0.0~3.x.x + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe249000b); + rv_csr_write(CSR_MXSTATUS, 0x438100); + rv_csr_write(CSR_MHINT, 0x31ea32c); + rv_csr_write(CSR_MHINT2, 0x180); + rv_csr_write(CSR_MHCR, 0x11ff & (~0x3)); + rv_csr_write(CSR_MHINT4, 0x2080); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else { + while(1); + } + break; + case 0x4: + if (cpu_ver >= 0x1002 && cpu_ver <= 0xffff) { + rv_csr_write(CSR_MHCR, 0x17f & (~0x3)); + rv_csr_write(CSR_MXSTATUS, 0x638000); + rv_csr_write(CSR_MHINT, 0x650c); + } else { + while(1); + } + break; + case 0x5: + if(cpu_tnmodel == 0) { //c908 + if (cpu_ver >= 0x0000 && cpu_ver <= 0x0007) { //0.0.0~0.0.7 + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xe0420008); + rv_csr_write(CSR_MXSTATUS, 0x638000); + rv_csr_write(CSR_MHINT, 0x2c50c); + rv_csr_write(CSR_MHCR, 0x11ff & (~0x3)); + } else if (cpu_ver >= 0x0040 && cpu_ver <= 0x1002) { //0.1.0~1.0.2 + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xa042000a); + rv_csr_write(CSR_MXSTATUS, 0x438000); + rv_csr_write(CSR_MHINT, 0x21aa10c); + rv_csr_write(CSR_MHCR, 0x10011ff & (~0x3)); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else if (cpu_ver >= 0x1003 && cpu_ver <= 0x100b) { //1.0.3~1.0.11 + + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xa042000a); + rv_csr_write(CSR_MXSTATUS, 0x438000); + rv_csr_write(CSR_MHINT, 0x1aa10c); + rv_csr_write(CSR_MHCR, 0x10011ff & (~0x3)); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else if (cpu_ver >= 0x100c && cpu_ver <= 0x1fff) { //1.0.12~ + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xa042000a); + rv_csr_write(CSR_MXSTATUS, 0x438100); + rv_csr_write(CSR_MHINT, 0x21aa10c); + rv_csr_write(CSR_MHCR, 0x10011ff & (~0x3)); + rv_csr_write(CSR_MHINT4, 0x10000080); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else if (cpu_ver >= 0x2000 && cpu_ver <= 0xffff) { //2.0.0~ + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xa042000a); + rv_csr_write(CSR_MXSTATUS, 0x438100); + rv_csr_write(CSR_MHINT, 0x21aa10c); + rv_csr_write(CSR_MHCR, 0x10011ff & (~0x3)); + rv_csr_write(CSR_MHINT4, 0x10000080); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else { + while(1); + } + } else if (cpu_tnmodel == 1) { + if (cpu_ver >= 0x0) { + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xA0420002); + rv_csr_write(CSR_MXSTATUS, 0x438100); + rv_csr_write(CSR_MHINT, 0x21AA10C); + rv_csr_write(CSR_MHCR, 0x10011FF & (~0x3)); + rv_csr_write(CSR_MHINT4, 0x10000080); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else { + while(1); + } + } else { + while(1); + } + break; + case 0x6: + if (cpu_ver >= 0x0) { + rv_csr_write(CSR_MSMPR, 0x1); + rv_csr_write(CSR_MCCR2, 0xA0420002); + rv_csr_write(CSR_MXSTATUS, 0x438000); + rv_csr_write(CSR_MHINT, 0x3A1AA10C); + rv_csr_write(CSR_MHCR, 0x10011BF & (~0x3)); +#if __riscv_xlen == 64 + rv_csr_write(CSR_MENVCFG, 0x4000000000000000); +#endif + } else { + while(1); + } + break; + case 0x7: + if (cpu_ver >= 0x0) { + rv_csr_clear(CSR_MXSTATUS, 0x1); + rv_csr_write(CSR_MISELECT,CSR_MNASTATUS); + rv_csr_write(CSR_MIREG,0x1e); + } else { + while(1); + } + break; + case 0x8: + if (cpu_ver >= 0x0) { + rv_csr_clear(CSR_MXSTATUS, 0x1); + rv_csr_write(CSR_MISELECT,CSR_MNASTATUS); + rv_csr_write(CSR_MIREG,0x1e); + } else { + while(1); + } + break; + default: + // FIXME: maybe qemu + break; + } +} diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/irq.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/irq.c new file mode 100644 index 000000000..dd38678ee --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/irq.c @@ -0,0 +1,282 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +extern uint32_t soc_irq_get_irq_num(void); +extern void soc_irq_end(uint32_t irq_num); + +#if CONFIG_AOS_OSAL +#include +#include +#define CSI_INTRPT_ENTER() aos_kernel_intrpt_enter() +#define CSI_INTRPT_EXIT() aos_kernel_intrpt_exit() +#else +#ifdef CONFIG_KERNEL_FREERTOS +#include +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) +#include +#define printk rt_kprintf +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 printk printf +#define CSI_INTRPT_ENTER() +#define CSI_INTRPT_EXIT() +#endif +#endif /* end CONFIG_AOS_OSAL */ + + +#if CONFIG_INTC_IMSIC_APLIC +csi_dev_t *g_cpu_irq_table[CONFIG_NR_CPUS][CONFIG_IRQ_NUM]; +volatile msi_entry_t g_msi_map[CONFIG_NR_CPUS][CONFIG_IRQ_NUM]; +#define g_irq_table g_cpu_irq_table[csi_get_cpu_id()] +#else +csi_dev_t *g_irq_table[CONFIG_IRQ_NUM]; +#endif + +#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 + +/** + \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) +{ +#if CONFIG_INTC_IMSIC_APLIC + int cpu_id = csi_get_cpu_id(); + int msi_num = csi_imsic_irqnum_alloc(cpu_id, MSI_SOURCE_APLIC, irq_num); + g_cpu_irq_table[cpu_id][msi_num] = dev; + csi_imsic_irq_attach(cpu_id, msi_num, irq_handler); +#else + dev->irq_handler = irq_handler; + g_irq_table[irq_num] = dev; +#endif +} + +/** + \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) +{ +#if CONFIG_INTC_IMSIC_APLIC + int cpu_id = csi_get_cpu_id(); + int msi_num = csi_imsic_irqnum_alloc(cpu_id, MSI_SOURCE_APLIC, irq_num); + g_cpu_irq_table[cpu_id][msi_num] = dev; + csi_imsic_irq_attach2(cpu_id, msi_num, irq_handler2, arg); +#else + dev->arg = arg; + dev->irq_handler2 = irq_handler2; + g_irq_table[irq_num] = dev; +#endif +} + +/** + \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) +{ +#if CONFIG_INTC_IMSIC_APLIC + int msi_num = csi_aplic_get_target_eiid(APLIC_BASE, irq_num); + int cpu_id = csi_aplic_get_target_hart(APLIC_BASE, irq_num); + CSI_ASSERT(csi_imsic_irq_detach(cpu_id, msi_num) == CSI_OK); + CSI_ASSERT(csi_imsic_irqnum_free(cpu_id, msi_num) == CSI_OK); + CSI_ASSERT(g_cpu_irq_table[cpu_id][msi_num] != NULL); + g_cpu_irq_table[cpu_id][msi_num] = NULL; +#else + g_irq_table[irq_num] = NULL; +#endif +} + +/** + \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 +} + +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 +} + +//FIXME: For Non CLIC mode +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 +} + +#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 /* CONFIG_ECC_L1_ENABLE || CONFIG_ECC_L2_ENABLE */ + +/** + \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 (irqn > sizeof(g_irq_table) / sizeof(g_irq_table[0]) - 1 ) { + printk("undefined interrupt: irqn = 0x%x\n", irqn); + while(1); + } + 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 { + printk("undefined interrupt2: irqn = 0x%x\n", irqn); + /*the interrupt has no registered isr*/ + while(1); + } + } else { + printk("null irq_handler: irqn = 0x%x\n", irqn); + while(1); + } + + 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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/irq_port.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/irq_port.c new file mode 100644 index 000000000..8caa0588f --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/irq_port.c @@ -0,0 +1,147 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 irq vector num + * @return irq no + */ +uint32_t soc_irq_get_irq_num(void) +{ + int hartid = csi_get_cpu_id(); +#if CONFIG_INTC_CLIC + (void) hartid; +#if CONFIG_RISCV_SMODE + return (__get_SCAUSE() & 0x3FFU); +#else + return (__get_MCAUSE() & 0x3FFU); +#endif /* CONFIG_RISCV_SMODE */ +#endif /* CONFIG_INTC_CLIC */ + +#if CONFIG_INTC_PLIC || CONFIG_INTC_CLIC_PLIC + uint32_t num; +#if CONFIG_RISCV_SMODE + uint32_t irqn = __get_SCAUSE() & 0x3FFU; +#else + uint32_t irqn = __get_MCAUSE() & 0x3FFU; +#endif /* CONFIG_RISCV_SMODE */ + if (irqn == Machine_External_IRQn || irqn == Supervisor_External_IRQn) { +#if CONFIG_RISCV_SMODE + num = PLIC_Hn_MSCLAIM_VAL(&PLIC->PLIC_H0_SCLAIM, hartid); +#else + num = PLIC_Hn_MSCLAIM_VAL(&PLIC->PLIC_H0_MCLAIM, hartid); +#endif +#if CONFIG_INTC_CLIC_PLIC + num += PLIC_IRQ_OFFSET; +#endif + } else { + num = irqn; + } + return num; +#endif /* CONFIG_INTC_PLIC || CONFIG_INTC_CLIC_PLIC */ + +#if CONFIG_INTC_APLIC || CONFIG_INTC_CLIC_APLIC + uint32_t num; +#if CONFIG_RISCV_SMODE + uint32_t irqn = __get_SCAUSE() & 0x3FFU; +#else + uint32_t irqn = __get_MCAUSE() & 0x3FFU; +#endif /* CONFIG_RISCV_SMODE */ + if (irqn == Machine_External_IRQn || irqn == Supervisor_External_IRQn) { + num = csi_aplic_read_claimi(APLIC_BASE, hartid); +#if CONFIG_INTC_CLIC_APLIC + num += APLIC_IRQ_OFFSET; +#endif + } else { + num = irqn; + } + return num; +#endif /* CONFIG_INTC_APLIC || CONFIG_INTC_CLIC_APLIC */ + +#if CONFIG_INTC_IMSIC_APLIC + return g_handing_msi_num[hartid]; +#endif +} + +void soc_irq_end(uint32_t irq_num) +{ +#if CONFIG_INTC_CLIC + // DO NOTHING +#endif /* CONFIG_INTC_CLIC */ + + /** + * If aplic works in msi-mode + * and the current interrupt is level-triggered + * need retrigger + */ +#if CONFIG_INTC_IMSIC_APLIC + extern csi_dev_t *g_cpu_irq_table[CONFIG_NR_CPUS][CONFIG_IRQ_NUM]; + csi_aplic_retrigger_level_irq(APLIC_BASE, g_cpu_irq_table[csi_get_cpu_id()][irq_num]->irq_num); +#endif + + +#if CONFIG_INTC_PLIC || CONFIG_INTC_CLIC_PLIC +#if CONFIG_INTC_CLIC_PLIC + if (irq_num <= PLIC_IRQ_OFFSET) { + return; + } + irq_num -= PLIC_IRQ_OFFSET; +#endif /* CONFIG_INTC_CLIC_PLIC */ +#if 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 /* CONFIG_INTC_PLIC || CONFIG_INTC_CLIC_PLIC */ + +#if CONFIG_INTC_APLIC || CONFIG_INTC_CLIC_APLIC + // DO NOTHING +#endif /* CONFIG_INTC_APLIC || CONFIG_INTC_CLIC_APLIC */ +} diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/pre_main.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/pre_main.c new file mode 100644 index 000000000..99e207c50 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/pre_main.c @@ -0,0 +1,103 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +#include +#include + +extern unsigned long __heap_start; +extern unsigned long __heap_end; +unsigned long g_heap_start = (unsigned long)&__heap_start; +unsigned long g_heap_end = (unsigned long)&__heap_end; + +extern int main(void); +/* + * 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__)); + +} + +__attribute__((weak)) void pre_main(void) +{ +#if (!defined(CONFIG_KERNEL_RHINO)) && (!defined(CONFIG_NUTTXMM_NONE)) \ + && (!defined(CONFIG_KERNEL_FREERTOS)) && (!defined(CONFIG_KERNEL_RTTHREAD)) \ + && (!defined(CONFIG_KERNEL_THREADX)) + extern void mm_heap_initialize(void); + mm_heap_initialize(); +#endif + + main(); +} diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/sys_clk.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/sys_clk.c new file mode 100644 index 000000000..2ef6f11e3 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/sys_clk.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 + +uint32_t g_system_clock = IHS_VALUE; + +#if CONFIG_BOARD_XIAOHUI_EVB +uint32_t soc_get_cpu_freq(uint32_t idx) +{ +#ifndef CONFIG_CPU_FREQ_HZ + return 50*1000000; +#else + return CONFIG_CPU_FREQ_HZ; +#endif +} + +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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/target_get.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/target_get.c new file mode 100644 index 000000000..da53b1df7 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/target_get.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. + */ + + +/****************************************************************************** + * @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 const csi_perip_info_t g_soc_info[]; +extern const csi_dma_ch_bit_spt_list_t dma_spt_list[]; +extern const csi_dma_handshake_list_t g_handshake_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_id; + uint16_t ctrl_id = 0; + uint16_t index = 0; + 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++) + { + if (list[ctrl_id] == NULL) + { + continue; + } + + 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 = ch_id; + dma_ch_info->ctrl_idx = (uint8_t)ctrl_id; + /* find the channel */ + return CSI_OK; + } + } + } + } + else + { + /* the MEM2PERH mode or PERH2MEM mode */ + for (spt_id = 0U; dma_spt_list[spt_id].parent_dev_id != DEV_IDX_INVALID; spt_id++) + { + if ((dma_spt_list[spt_id].parent_dev_id == parent_dev->idx)) + { + const csi_dma_ch_bit_desc_t *dev_ch_info = dma_spt_list[spt_id].ch_list; + + for (index = 0U; dev_ch_info[index].ctrl_idx != DEV_IDX_INVALID; index++) + { + uint16_t tem_idx = dev_ch_info[index].ctrl_idx; + for (ch_id = 0U; ch_id < list[tem_idx]->ch_num; ch_id++) + { + + if (!(list[tem_idx]->alloc_status & ((uint32_t)1 << ch_id)) && (dev_ch_info[index].ch_bit_info & ((uint32_t)1 << ch_id))) + { + dma_ch_info->ch_idx = ch_id; + dma_ch_info->ctrl_idx = (uint8_t)tem_idx; + return CSI_OK; + } + } + } + return CSI_ERROR; + } + + } + } + return CSI_ERROR; +} + +csi_error_t target_get_check_dma_access(uint32_t ctrl_idx, void *srcaddr, void *dstaddr, void **dma_base_src_addr, void **dma_base_dst_addr) +{ + *dma_base_src_addr = srcaddr; + *dma_base_dst_addr = dstaddr; + return CSI_OK; +} + +csi_error_t target_get_dma_handshake(uint16_t dma_id, uint16_t dev_id, uint16_t dev_tag, uint8_t type, uint16_t *handshake) +{ + const csi_dma_handshake_list_t *handshake_list = &g_handshake_list[0]; + uint16_t index = 0; + uint8_t dma_found_flag = 0; + uint8_t dev_found_flag = 0; + + for (index = 0; handshake_list[index].ctrl_idx != DEV_IDX_INVALID; index++) + { + if (handshake_list[index].ctrl_idx == dma_id) + { + dma_found_flag = 0x1; + break; + } + } + + if (!dma_found_flag) + { + return CSI_UNSUPPORTED; + } + + const csi_dma_handshake_ctrl_t *handshake_ctrl_list = handshake_list[index].handshake_ctrl_list; + + for (index = 0; handshake_ctrl_list[index].parent_dev_id != DEV_IDX_INVALID; index++) + { + if (handshake_ctrl_list[index].parent_dev_id == dev_id && handshake_ctrl_list[index].dev_tag == dev_tag) + { + if (type == DMA_HANDSHAKE_TYPE_RX && handshake_ctrl_list[index].rx_hs != DMA_HANDSHAKE_NONE) + { + *handshake = handshake_ctrl_list[index].rx_hs; + dev_found_flag = 0x1; + } + else if (type == DMA_HANDSHAKE_TYPE_TX && handshake_ctrl_list[index].tx_hs != DMA_HANDSHAKE_NONE) + { + *handshake = handshake_ctrl_list[index].tx_hs; + dev_found_flag = 0x1; + } + break; + } + } + + if (!dev_found_flag) + { + return CSI_UNSUPPORTED; + } + return CSI_OK; +} diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/tick.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/tick.c new file mode 100644 index 000000000..1f121916a --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/tick.c @@ -0,0 +1,341 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +#define __WEAK __attribute__((weak)) + +// from 1970-01-01 00:00:00 UTC +static volatile uint64_t timestamp_us_offset; + +#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; + +#ifdef CONFIG_TIMER_FOR_TICK +static csi_timer_t tick_timer; +#ifndef CONFIG_TICK_TIMER_IDX +#define CONFIG_TICK_TIMER_IDX 0U +#endif +#else /* !CONFIG_TIMER_FOR_TICK */ +static csi_dev_t tick_dev; +static volatile uint64_t timer_init_value = 0U; +#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 +} + +#ifdef CONFIG_TIMER_FOR_TICK +void tick_event_cb(csi_timer_t *timer_handle, void *arg) +{ + csi_tick_increase(); +#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) + extern void rt_tick_increase(void); + rt_tick_increase(); +#elif defined(CONFIG_KERNEL_THREADX) + extern void _tx_timer_interrupt(void); + _tx_timer_interrupt(); +#else +#endif +#endif /* end CONFIG_AOS_OSAL */ +} +#else /* !CONFIG_TIMER_FOR_TICK */ +void tick_irq_handler(void *arg) +{ + csi_tick_increase(); + csi_coret_config((soc_get_coretim_freq() / CONFIG_SYSTICK_HZ), tick_dev.irq_num); +#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) + extern void rt_tick_increase(void); + rt_tick_increase(); +#elif defined(CONFIG_KERNEL_THREADX) + extern void _tx_timer_interrupt(void); + _tx_timer_interrupt(); +#else +#endif +#endif /* end CONFIG_AOS_OSAL */ + +} +#endif /* CONFIG_TIMER_FOR_TICK */ + +csi_error_t csi_tick_init(void) +{ +#if defined(CONFIG_SMP) && CONFIG_SMP + csi_tick[csi_get_cpu_id()] = 0; +#else + csi_tick = 0U; +#endif + +#ifdef CONFIG_TIMER_FOR_TICK + csi_error_t ret = csi_timer_init(&tick_timer, CONFIG_TICK_TIMER_IDX); + if (ret == CSI_OK) { + ret = csi_timer_attach_callback(&tick_timer, tick_event_cb, NULL); + if (ret == CSI_OK) { + ret = csi_timer_start(&tick_timer, (1000000U / CONFIG_SYSTICK_HZ)); + } + } + return ret; +#else /* !CONFIG_TIMER_FOR_TICK */ +#if CONFIG_RISCV_SMODE + tick_dev.irq_num = Supervisor_Timer_IRQn; +#else + tick_dev.irq_num = CORET_IRQn; +#endif +#if CONFIG_CPU_XUANTIE_E9XX || CONFIG_INTC_CLIC || CONFIG_INTC_CLIC_PLIC || CONFIG_INTC_CLIC_APLIC + csi_vic_set_prio(tick_dev.irq_num, 2); + csi_irq_attach(tick_dev.irq_num, &tick_irq_handler, &tick_dev); +#endif /* CONFIG_CPU_XUANTIE_E9XX || CONFIG_INTC_CLIC || CONFIG_INTC_CLIC_PLIC || CONFIG_INTC_CLIC_APLIC */ + timer_init_value = csi_coret_get_value2(); + csi_coret_reset_value2(); + csi_coret_config((soc_get_coretim_freq() / CONFIG_SYSTICK_HZ), tick_dev.irq_num); + csi_coret_irq_enable(); +#endif /* CONFIG_TIMER_FOR_TICK */ + return CSI_OK; +} + +void csi_tick_uninit(void) +{ +#ifdef CONFIG_TIMER_FOR_TICK + csi_timer_stop(&tick_timer); + csi_timer_uninit(&tick_timer); +#else + csi_coret_irq_disable(); +#if CONFIG_CPU_XUANTIE_E9XX || CONFIG_INTC_CLIC_PLIC + csi_irq_detach(tick_dev.irq_num); +#endif +#endif /* CONFIG_TIMER_FOR_TICK */ +} + +#ifdef CONFIG_TIMER_FOR_TICK +uint32_t csi_tick_get_ms(void) +{ + uint32_t time = last_time_ms, freq; + freq = csi_timer_get_load_value(&tick_timer) * CONFIG_SYSTICK_HZ; + + while (freq) { + time = (csi_tick * (1000U / CONFIG_SYSTICK_HZ)) + ((csi_timer_get_load_value(&tick_timer) - csi_timer_get_remaining_value(&tick_timer)) / (freq / 1000U)); + + if (time >= last_time_ms) { + break; + } + } + + last_time_ms = time; + return time; +} + +uint64_t csi_tick_get_us(void) +{ + uint64_t time, freq; + uint32_t temp; + freq = soc_get_timer_freq(CONFIG_TICK_TIMER_IDX); + + while (1) { + /* the time of coretim pass */ + temp = csi_timer_get_load_value(&tick_timer) - csi_timer_get_remaining_value(&tick_timer); + time = ((uint64_t)temp * 1000U) / (freq / 1000U); + /* the time of csi_tick */ + time += ((uint64_t)csi_tick * (1000000U / CONFIG_SYSTICK_HZ)); + + if (time >= last_time_us) { + break; + } + } + + last_time_us = time; + return time; +} + +static void _mdelay(void) +{ + uint32_t load = csi_timer_get_load_value(&tick_timer); + uint32_t start_r = csi_timer_get_remaining_value(&tick_timer); + uint32_t cur_r; + uint32_t cnt = (soc_get_timer_freq(CONFIG_TICK_TIMER_IDX) / 1000U); + + while (1) { + cur_r = csi_timer_get_remaining_value(&tick_timer); + + if (start_r > cur_r) { + if ((start_r - cur_r) >= cnt) { + break; + } + } else { + if (((load - cur_r) + start_r) >= cnt) { + break; + } + } + } +} + +static void _10udelay(void) +{ + uint32_t load = csi_timer_get_load_value(&tick_timer); + uint32_t start_r = csi_timer_get_remaining_value(&tick_timer); + uint32_t cur_r; + uint32_t cnt = (soc_get_timer_freq(CONFIG_TICK_TIMER_IDX) / 100000U); + + while (1) { + cur_r = csi_timer_get_remaining_value(&tick_timer); + + if (start_r > cur_r) { + if ((start_r - cur_r) >= cnt) { + break; + } + } else { + if (((load - cur_r) + start_r) >= cnt) { + break; + } + } + } +} + +#else /* !CONFIG_TIMER_FOR_TICK */ + +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; + } + } + } +} +#endif + +void csi_set_calendar_us(uint64_t timestamp) +{ + timestamp_us_offset = timestamp; +} + +uint64_t csi_get_calendar_us(void) +{ + return csi_tick_get_us() + timestamp_us_offset; +} + +__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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/weak.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/weak.c new file mode 100644 index 000000000..d6e326552 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/weak.c @@ -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 weak.c + * @brief source file for the weak + * @version V1.0 + * @date 04. April 2024 + ******************************************************************************/ + +#include +#include +#include + +__WEAK void soc_dcache_clean_invalid_range(unsigned long addr, uint32_t size) +{ + csi_dcache_clean_invalid_range((unsigned long *)addr, size); +} + +__WEAK void soc_dcache_clean_invalid_all(void) +{ + csi_dcache_clean_invalid(); +} + +__WEAK void soc_dcache_invalid_range(unsigned long addr, uint32_t size) +{ + csi_dcache_invalid_range((unsigned long *)addr, size); +} + +__WEAK void soc_dcache_clean(void) +{ + csi_dcache_clean(); +} + +__WEAK void soc_icache_invalid(void) +{ + csi_icache_invalid(); +} + +__WEAK unsigned long soc_dma_address_remap(unsigned long addr) +{ + return addr; +} diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/README.txt b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/README.txt new file mode 100644 index 000000000..bb1bf4a3d --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/README.txt @@ -0,0 +1 @@ +Just include csi_core.h! diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/core_rv32.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/core_rv32.h new file mode 100644 index 000000000..c46e8428f --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/core_rv32.h @@ -0,0 +1,1452 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 */ +} pmp_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 */ + +#if CONFIG_CPU_XUANTIE_E902 || CONFIG_CPU_XUANTIE_E902M || CONFIG_CPU_XUANTIE_E902T || CONFIG_CPU_XUANTIE_E902MT \ + || CONFIG_CPU_XUANTIE_E901PLUS_CP || CONFIG_CPU_XUANTIE_E901PLUS_B_CP || CONFIG_CPU_XUANTIE_E901PLUS_M_CP || CONFIG_CPU_XUANTIE_E901PLUS_BM_CP \ + || CONFIG_CPU_XUANTIE_E901_CP || CONFIG_CPU_XUANTIE_E901_B_CP || CONFIG_CPU_XUANTIE_E901_ZM_CP || CONFIG_CPU_XUANTIE_E901_BZM_CP +#define CACHE_INV_ADDR_Pos 4U +#else +#define CACHE_INV_ADDR_Pos 5U +#endif +#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 */ +#ifndef CONFIG_TCIP_BASE +#define CONFIG_TCIP_BASE 0xE0000000UL +#endif +#define CORET_BASE (CONFIG_TCIP_BASE + 0x4000UL) /*!< CORET Base Address */ +#define CLIC_BASE (CONFIG_TCIP_BASE + 0x800000UL) /*!< 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_E902 || CONFIG_CPU_XUANTIE_E902M || CONFIG_CPU_XUANTIE_E902T || CONFIG_CPU_XUANTIE_E902MT \ + || CONFIG_CPU_XUANTIE_E901PLUS_CP || CONFIG_CPU_XUANTIE_E901PLUS_B_CP || CONFIG_CPU_XUANTIE_E901PLUS_M_CP || CONFIG_CPU_XUANTIE_E901PLUS_BM_CP \ + || CONFIG_CPU_XUANTIE_E901_CP || CONFIG_CPU_XUANTIE_E901_B_CP || CONFIG_CPU_XUANTIE_E901_ZM_CP || CONFIG_CPU_XUANTIE_E901_BZM_CP + return 16; +#else + return 32; +#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; + __DSB(); +} + +/** + \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; + __DSB(); +} + +/** + \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; + uint8_t ctl = CLIC->CLICINT[IRQn].CTL; + ctl <<= nlbits; + ctl >>= nlbits; + CLIC->CLICINT[IRQn].CTL = ctl | (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; + __DSB(); + 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 physical memory protection region. + \details + \param [in] idx memory protection 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 protection region size. + \param [in] attr \ref pmp_region_attr_t. memory protection region attribute. + \param [in] enable enable or disable memory protection region. + */ +__STATIC_INLINE void csi_pmp_config_region(uint32_t idx, unsigned long base_addr, region_size_e size, + pmp_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 physical memory protection region by idx. + \details + \param [in] idx memory protection region (0, 1, 2, ..., 15). + */ +__STATIC_INLINE void csi_pmp_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, uint64_t ticks, int32_t IRQn) +{ + CORET_Type *coret = (CORET_Type *)coret_base; + if ((coret->MTIMECMP != 0) && (coret->MTIMECMP != 0xFFFFFFFFFFFFFFFFULL)) { + 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(uint64_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(); + __ICACHE_IALL(); + cache = __get_MHCR(); + cache |= CACHE_MHCR_IE_Msk; + __set_MHCR(cache); + __DSB(); + } +#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(); + cache = __get_MHCR(); + cache &= ~CACHE_MHCR_IE_Msk; /* disable icache */ + __set_MHCR(cache); + __ICACHE_IALL(); /* invalidate all icache */ + __DSB(); + } +#endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_INLINE void csi_icache_invalid (void) +{ +#if (__ICACHE_PRESENT == 1U) + __DSB(); + __ICACHE_IALL(); /* invalidate all icache */ + __DSB(); +#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(); + __DCACHE_IALL(); /* invalidate all dcache */ + cache = __get_MHCR(); + cache |= CACHE_MHCR_DE_Msk; /* enable dcache */ + __set_MHCR(cache); + + __DSB(); + } +#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(); + cache = __get_MHCR(); + cache &= ~(uint32_t)CACHE_MHCR_DE_Msk; /* disable all Cache */ + __set_MHCR(cache); + __DCACHE_IALL(); /* invalidate all Cache */ + __DSB(); + } +#endif +} + + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_INLINE void csi_dcache_invalid (void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __DCACHE_IALL(); /* invalidate all Cache */ + __DSB(); +#endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_INLINE void csi_dcache_clean (void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __DCACHE_CALL(); /* clean all Cache */ + __DSB(); +#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(); + __DCACHE_CIALL(); /* clean and inv all Cache */ + __DSB(); +#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 & CACHE_INV_ADDR_Msk; + + __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 & CACHE_INV_ADDR_Msk; + + __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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/core_rv64.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/core_rv64.h new file mode 100644 index 000000000..c5463e936 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/core_rv64.h @@ -0,0 +1,2002 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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; + __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 */ +} pmp_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 \ + || CONFIG_CPU_XUANTIE_R908_CP_XT || CONFIG_CPU_XUANTIE_R908FD_CP_XT || CONFIG_CPU_XUANTIE_R908FDV_CP_XT \ + || CONFIG_CPU_XUANTIE_C908X || CONFIG_CPU_XUANTIE_C908X_CP || CONFIG_CPU_XUANTIE_C908X_CP_XT +#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 (~((0x1ULL << CACHE_INV_ADDR_Pos) - 1)) + +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 ((uint32_t)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 ((uint32_t)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 ((uint32_t)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 ((uint32_t)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 ((uint32_t)IRQn > PLIC_IRQ_OFFSET) { + IRQn -= PLIC_IRQ_OFFSET; + } else { + CLIC->CLICINT[IRQn].IP |= CLIC_INTIP_IP_Msk; + __DSB(); + return; + } +#endif + plic->PLIC_IP[IRQn/32] = plic->PLIC_IP[IRQn/32] | (0x1 << (IRQn%32)); + __DSB(); +} + +/** + \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 ((uint32_t)IRQn > PLIC_IRQ_OFFSET) { + IRQn -= PLIC_IRQ_OFFSET; + } else { + CLIC->CLICINT[IRQn].IP &= ~CLIC_INTIP_IP_Msk; + __DSB(); + return; + } +#endif + plic->PLIC_H0_SCLAIM = IRQn; + __DSB(); +} + +/** + \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 ((uint32_t)IRQn > PLIC_IRQ_OFFSET) { + IRQn -= PLIC_IRQ_OFFSET; + } else { + uint8_t nlbits = (CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos; + uint8_t ctl = CLIC->CLICINT[IRQn].CTL; + ctl <<= nlbits; + ctl >>= nlbits; + CLIC->CLICINT[IRQn].CTL = ctl | (priority << (8 - nlbits)); + __DSB(); + return; + } +#endif + plic->PLIC_PRIO[IRQn - 1] = priority; + __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) +{ + PLIC_Type *plic = (PLIC_Type *)CONFIG_PLIC_BASE; +#if CONFIG_INTC_CLIC_PLIC + if ((uint32_t)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 physical memory protection region. + \details + \param [in] idx memory protection 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 protection region size. + \param [in] attr \ref pmp_region_attr_t. memory protection region attribute. + \param [in] enable enable or disable memory protection region. + */ +__STATIC_INLINE void csi_pmp_config_region(uint32_t idx, unsigned long base_addr, region_size_e size, + pmp_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) & (0xFFFFFFFFFFFFFFFFUL - ((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 physical memory protection region by idx. + \details + \param [in] idx memory protection region (0, 1, 2, ..., 15). + */ +__STATIC_INLINE void csi_pmp_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, uint64_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(uint64_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(); + __ICACHE_IALL(); + cache = __get_MHCR(); + cache |= CACHE_MHCR_IE_Msk; + __set_MHCR(cache); + __DSB(); + } +#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(); + cache = __get_MHCR(); + cache &= ~CACHE_MHCR_IE_Msk; /* disable icache */ + __set_MHCR(cache); + __ICACHE_IALL(); /* invalidate all icache */ + __DSB(); + } +#endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_INLINE void csi_icache_invalid(void) +{ +#if (__ICACHE_PRESENT == 1U) + __DSB(); + __ICACHE_IALL(); /* invalidate all icache */ + __DSB(); +#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(); + __DCACHE_IALL(); /* invalidate all dcache */ + cache = __get_MHCR(); + cache |= CACHE_MHCR_DE_Msk; /* enable dcache */ + __set_MHCR(cache); + + __DSB(); + } +#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(); + cache = __get_MHCR(); + cache &= ~(uint32_t)CACHE_MHCR_DE_Msk; /* disable all Cache */ + __set_MHCR(cache); + __DCACHE_IALL(); /* invalidate all Cache */ + __DSB(); + } +#endif +} + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_INLINE void csi_dcache_invalid(void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __DCACHE_IALL(); /* invalidate all Cache */ + __DSB(); +#endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_INLINE void csi_dcache_clean(void) +{ +#if (__DCACHE_PRESENT == 1U) + __DSB(); + __DCACHE_CALL(); /* clean all Cache */ + __DSB(); +#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(); + __DCACHE_CIALL(); /* clean and inv all Cache */ + __DSB(); +#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 & CACHE_INV_ADDR_Msk; + + __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 & CACHE_INV_ADDR_Msk; + + __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_C908X || CONFIG_CPU_XUANTIE_C908X_CP || CONFIG_CPU_XUANTIE_C908X_CP_XT \ + || CONFIG_CPU_XUANTIE_C910 || CONFIG_CPU_XUANTIE_C920 \ + || CONFIG_CPU_XUANTIE_C910V2 || CONFIG_CPU_XUANTIE_C920V2 \ + || CONFIG_CPU_XUANTIE_C910V3 || CONFIG_CPU_XUANTIE_C920V3 \ + || CONFIG_CPU_XUANTIE_C910V3_CP || CONFIG_CPU_XUANTIE_C920V3_CP \ + || CONFIG_CPU_XUANTIE_C910V3_CP_XT || CONFIG_CPU_XUANTIE_C920V3_CP_XT \ + || 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_R908_CP_XT || CONFIG_CPU_XUANTIE_R908FD_CP_XT || CONFIG_CPU_XUANTIE_R908FDV_CP_XT \ + || 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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv32_gcc.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv32_gcc.h new file mode 100644 index 000000000..4c7d540cf --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv32_gcc.h @@ -0,0 +1,3374 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 \ + || CONFIG_CPU_XUANTIE_E901PLUS_CP || CONFIG_CPU_XUANTIE_E901PLUS_B_CP || CONFIG_CPU_XUANTIE_E901PLUS_M_CP || CONFIG_CPU_XUANTIE_E901PLUS_BM_CP \ + || CONFIG_CPU_XUANTIE_E901_CP || CONFIG_CPU_XUANTIE_E901_B_CP || CONFIG_CPU_XUANTIE_E901_ZM_CP || CONFIG_CPU_XUANTIE_E901_BZM_CP +#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 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)); + return (result); +} + +/** + \brief Get MTIMEH + \details Returns the content of the MTIME Register. + \return MTIME Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTIMEH(void) +{ + unsigned long result; + __ASM volatile("rdtimeh %0" : "=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 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)); +} + +#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 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; + } +} + +/** + \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"); +#if __riscv_xtheadsync + __ASM volatile("sync"); +#endif +} + +/** + \brief Invalid all icache + \details invalid all icache. + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IALL(void) +{ +#if __riscv_xtheadcmo + __ASM volatile("icache.iall"); +#endif +} + +/** + \brief Invalid Icache by addr + \details Invalid Icache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IPA(unsigned long addr) +{ +#if __riscv_xtheadcmo + __ASM volatile("icache.ipa %0" : : "r"(addr)); +#endif +} + +/** + \brief Invalid all dcache + \details invalid all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IALL(void) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.iall"); +#endif +} + +/** + \brief Clear all dcache + \details clear all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CALL(void) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.call"); +#endif +} + +/** + \brief Clear&invalid all dcache + \details clear & invalid all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIALL(void) +{ +#if __riscv_xtheadcmo + __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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.ipa %0" : : "r"(addr)); +#endif +} + +/** + \brief Clear Dcache by addr + \details Clear Dcache by addr. + \param [in] addr operate addr + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CPA(unsigned long addr) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.cpa %0" : : "r"(addr)); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.cipa %0" : : "r"(addr)); +#endif +} + + +/** + \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); +} + +#if 0 +/** + \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); +} +#endif + +/** + \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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv64_gcc.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv64_gcc.h new file mode 100644 index 000000000..9878668e2 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv64_gcc.h @@ -0,0 +1,4383 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_C908X || CONFIG_CPU_XUANTIE_C908X_CP || CONFIG_CPU_XUANTIE_C908X_CP_XT \ + || CONFIG_CPU_XUANTIE_C910V2 || CONFIG_CPU_XUANTIE_C920V2 \ + || CONFIG_CPU_XUANTIE_C910V3 || CONFIG_CPU_XUANTIE_C920V3 \ + || CONFIG_CPU_XUANTIE_C910V3_CP || CONFIG_CPU_XUANTIE_C920V3_CP \ + || CONFIG_CPU_XUANTIE_C910V3_CP_XT || CONFIG_CPU_XUANTIE_C920V3_CP_XT \ + || 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_R908_CP_XT || CONFIG_CPU_XUANTIE_R908FD_CP_XT || CONFIG_CPU_XUANTIE_R908FDV_CP_XT +#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 MTIMEH + \details Returns the content of the MTIME Register. + \return MTIME Register value + */ +__ALWAYS_STATIC_INLINE unsigned long __get_MTIMEH(void) +{ + unsigned long result; + __ASM volatile("rdtimeh %0" : "=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"); +#if __riscv_xtheadsync + __ASM volatile("sync"); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadsync + __ASM volatile("sync.is"); +#endif +} + +/** + \brief Invalid all icache + \details invalid all icache. + */ +__ALWAYS_STATIC_INLINE void __ICACHE_IALL(void) +{ +#if __riscv_xtheadcmo + __ASM volatile("icache.iall"); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("icache.ialls"); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("icache.ipa %0" : : "r"(addr)); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("icache.iva %0" : : "r"(addr)); +#endif +} + +/** + \brief Invalid all L1dcache + \details invalid all L1dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_IALL(void) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.iall"); +#endif +} + +/** + \brief Clear all dcache + \details clear all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CALL(void) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.call"); +#endif +} + +/** + \brief Clear & invalid all dcache + \details clear & invalid all dcache. + */ +__ALWAYS_STATIC_INLINE void __DCACHE_CIALL(void) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.ciall"); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.cisw %0" : : "r"(wayset)); +#endif +} + +#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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.cpa %0" : : "r"(addr)); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.cva %0" : : "r"(addr)); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.cipa %0" : : "r"(addr)); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.civa %0" : : "r"(addr)); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.ipa %0" : : "r"(addr)); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.iva %0" : : "r"(addr)); +#endif +} + +#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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.cpal1 %0" : : "r"(addr)); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.cval1 %0" : : "r"(addr)); +#endif +} + +/** + \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) +{ +#if __riscv_xtheadcmo + __ASM volatile("dcache.isw %0" : : "r"(wayset)); +#endif +} + +#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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv_common.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv_common.h new file mode 100644 index 000000000..4a57b718b --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv_common.h @@ -0,0 +1,126 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv_encoding.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv_encoding.h new file mode 100644 index 000000000..82df61a9d --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/core/csi_rv_encoding.h @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_ENCODING_H__ +#define __CSI_RV_ENCODING_H__ + +/* ===== User-level CSRs ===== */ + +/* User Trap Setup (N-extension) */ +#define CSR_USTATUS 0x000 +#define CSR_UIE 0x004 +#define CSR_UTVEC 0x005 + +/* User Trap Handling (N-extension) */ +#define CSR_USCRATCH 0x040 +#define CSR_UEPC 0x041 +#define CSR_UCAUSE 0x042 +#define CSR_UTVAL 0x043 +#define CSR_UIP 0x044 + +/* User Floating-point CSRs */ +#define CSR_FFLAGS 0x001 +#define CSR_FRM 0x002 +#define CSR_FCSR 0x003 + +/* User Vector CSRs */ +#define CSR_VSTART 0x008 +#define CSR_VXSAT 0x009 +#define CSR_VXRM 0x00A +#define CSR_VCSR 0x00F +#define CSR_VL 0xC20 +#define CSR_VTYPE 0xC21 +#define CSR_VLENB 0xC22 + +/* User Counters/Timers */ +#define CSR_CYCLE 0xc00 +#define CSR_TIME 0xc01 +#define CSR_INSTRET 0xc02 +#define CSR_HPMCOUNTER3 0xc03 +#define CSR_HPMCOUNTER4 0xc04 +#define CSR_HPMCOUNTER5 0xc05 +#define CSR_HPMCOUNTER6 0xc06 +#define CSR_HPMCOUNTER7 0xc07 +#define CSR_HPMCOUNTER8 0xc08 +#define CSR_HPMCOUNTER9 0xc09 +#define CSR_HPMCOUNTER10 0xc0a +#define CSR_HPMCOUNTER11 0xc0b +#define CSR_HPMCOUNTER12 0xc0c +#define CSR_HPMCOUNTER13 0xc0d +#define CSR_HPMCOUNTER14 0xc0e +#define CSR_HPMCOUNTER15 0xc0f +#define CSR_HPMCOUNTER16 0xc10 +#define CSR_HPMCOUNTER17 0xc11 +#define CSR_HPMCOUNTER18 0xc12 +#define CSR_HPMCOUNTER19 0xc13 +#define CSR_HPMCOUNTER20 0xc14 +#define CSR_HPMCOUNTER21 0xc15 +#define CSR_HPMCOUNTER22 0xc16 +#define CSR_HPMCOUNTER23 0xc17 +#define CSR_HPMCOUNTER24 0xc18 +#define CSR_HPMCOUNTER25 0xc19 +#define CSR_HPMCOUNTER26 0xc1a +#define CSR_HPMCOUNTER27 0xc1b +#define CSR_HPMCOUNTER28 0xc1c +#define CSR_HPMCOUNTER29 0xc1d +#define CSR_HPMCOUNTER30 0xc1e +#define CSR_HPMCOUNTER31 0xc1f +#define CSR_CYCLEH 0xc80 +#define CSR_TIMEH 0xc81 +#define CSR_INSTRETH 0xc82 +#define CSR_HPMCOUNTER3H 0xc83 +#define CSR_HPMCOUNTER4H 0xc84 +#define CSR_HPMCOUNTER5H 0xc85 +#define CSR_HPMCOUNTER6H 0xc86 +#define CSR_HPMCOUNTER7H 0xc87 +#define CSR_HPMCOUNTER8H 0xc88 +#define CSR_HPMCOUNTER9H 0xc89 +#define CSR_HPMCOUNTER10H 0xc8a +#define CSR_HPMCOUNTER11H 0xc8b +#define CSR_HPMCOUNTER12H 0xc8c +#define CSR_HPMCOUNTER13H 0xc8d +#define CSR_HPMCOUNTER14H 0xc8e +#define CSR_HPMCOUNTER15H 0xc8f +#define CSR_HPMCOUNTER16H 0xc90 +#define CSR_HPMCOUNTER17H 0xc91 +#define CSR_HPMCOUNTER18H 0xc92 +#define CSR_HPMCOUNTER19H 0xc93 +#define CSR_HPMCOUNTER20H 0xc94 +#define CSR_HPMCOUNTER21H 0xc95 +#define CSR_HPMCOUNTER22H 0xc96 +#define CSR_HPMCOUNTER23H 0xc97 +#define CSR_HPMCOUNTER24H 0xc98 +#define CSR_HPMCOUNTER25H 0xc99 +#define CSR_HPMCOUNTER26H 0xc9a +#define CSR_HPMCOUNTER27H 0xc9b +#define CSR_HPMCOUNTER28H 0xc9c +#define CSR_HPMCOUNTER29H 0xc9d +#define CSR_HPMCOUNTER30H 0xc9e +#define CSR_HPMCOUNTER31H 0xc9f + +/* ===== Supervisor-level CSRs ===== */ + +/* Supervisor Trap Setup */ +#define CSR_SSTATUS 0x100 +#define CSR_SIE 0x104 +#define CSR_STVEC 0x105 +#define CSR_SCOUNTEREN 0x106 + +/* Supervisor Counter Overflow CSR */ +#define CSR_SCOUNTOVF 0xda0 + +/* Supervisor Configuration */ +#define CSR_SENVCFG 0x10a + +/* Supervisor Trap Handling */ +#define CSR_SSCRATCH 0x140 +#define CSR_SEPC 0x141 +#define CSR_SCAUSE 0x142 +#define CSR_STVAL 0x143 +#define CSR_SIP 0x144 + +/* Supervisor CLIC CSRs */ +#define CSR_STVT 0x107 +#define CSR_SNXTI 0x145 +#define CSR_SINTSTATUS 0xDB1 +#define CSR_SINTTHRESH 0x147 +#define CSR_SSCRATCHCSW 0x148 +#define CSR_SSCRATCHCSWL 0x149 + +/* Sstc extension */ +#define CSR_STIMECMP 0x14D +#define CSR_STIMECMPH 0x15D + +/* Supervisor Protection and Translation */ +#define CSR_SATP 0x180 + +/* Supervisor Debug/Trace */ +#define CSR_SCONTEXT 0x5a8 + +/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */ +#define CSR_SISELECT 0x150 +#define CSR_SIREG 0x151 +#define CSR_SIREG2 0x152 +#define CSR_SIREG3 0x153 +#define CSR_SIREG4 0x155 +#define CSR_SIREG5 0x156 +#define CSR_SIREG6 0x157 + +/* Supervisor-Level Interrupts (AIA) */ +#define CSR_STOPEI 0x15c +#define CSR_STOPI 0xdb0 + +/* Supervisor-Level High-Half CSRs (AIA) */ +#define CSR_SIEH 0x114 +#define CSR_SIPH 0x154 + +/* Supervisor stateen CSRs */ +#define CSR_SSTATEEN0 0x10C +#define CSR_SSTATEEN1 0x10D +#define CSR_SSTATEEN2 0x10E +#define CSR_SSTATEEN3 0x10F + +/* ===== Hypervisor-level CSRs ===== */ + +/* Hypervisor Trap Setup (H-extension) */ +#define CSR_HSTATUS 0x600 +#define CSR_HEDELEG 0x602 +#define CSR_HIDELEG 0x603 +#define CSR_HIE 0x604 +#define CSR_HCOUNTEREN 0x606 +#define CSR_HGEIE 0x607 + +/* Hypervisor Configuration */ +#define CSR_HENVCFG 0x60a +#define CSR_HENVCFGH 0x61a + +/* Hypervisor Trap Handling (H-extension) */ +#define CSR_HTVAL 0x643 +#define CSR_HIP 0x644 +#define CSR_HVIP 0x645 +#define CSR_HTINST 0x64a +#define CSR_HGEIP 0xe12 + +/* Hypervisor Protection and Translation (H-extension) */ +#define CSR_HGATP 0x680 + +/* Hypervisor Counter/Timer Virtualization Registers (H-extension) */ +#define CSR_HTIMEDELTA 0x605 +#define CSR_HTIMEDELTAH 0x615 + +/* Virtual Supervisor Registers (H-extension) */ +#define CSR_VSSTATUS 0x200 +#define CSR_VSIE 0x204 +#define CSR_VSTVEC 0x205 +#define CSR_VSSCRATCH 0x240 +#define CSR_VSEPC 0x241 +#define CSR_VSCAUSE 0x242 +#define CSR_VSTVAL 0x243 +#define CSR_VSIP 0x244 +#define CSR_VSATP 0x280 + +/* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */ +#define CSR_HVIEN 0x608 +#define CSR_HVICTL 0x609 +#define CSR_HVIPRIO1 0x646 +#define CSR_HVIPRIO2 0x647 + +/* VS-Level Window to Indirectly Accessed Registers (H-extension with AIA) */ +#define CSR_VSISELECT 0x250 +#define CSR_VSIREG 0x251 + +/* VS-Level Interrupts (H-extension with AIA) */ +#define CSR_VSTOPEI 0x25c +#define CSR_VSTOPI 0xeb0 + +/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */ +#define CSR_HIDELEGH 0x613 +#define CSR_HVIENH 0x618 +#define CSR_HVIPH 0x655 +#define CSR_HVIPRIO1H 0x656 +#define CSR_HVIPRIO2H 0x657 +#define CSR_VSIEH 0x214 +#define CSR_VSIPH 0x254 + +/* Hypervisor stateen CSRs */ +#define CSR_HSTATEEN0 0x60C +#define CSR_HSTATEEN0H 0x61C +#define CSR_HSTATEEN1 0x60D +#define CSR_HSTATEEN1H 0x61D +#define CSR_HSTATEEN2 0x60E +#define CSR_HSTATEEN2H 0x61E +#define CSR_HSTATEEN3 0x60F +#define CSR_HSTATEEN3H 0x61F + +/* ===== Machine-level CSRs ===== */ + +/* Machine Information Registers */ +#define CSR_MVENDORID 0xf11 +#define CSR_MARCHID 0xf12 +#define CSR_MIMPID 0xf13 +#define CSR_MHARTID 0xf14 +#define CSR_MCONFIGPTR 0xf15 + +/* Machine Trap Setup */ +#define CSR_MSTATUS 0x300 +#define CSR_MISA 0x301 +#define CSR_MEDELEG 0x302 +#define CSR_MIDELEG 0x303 +#define CSR_MIE 0x304 +#define CSR_MTVEC 0x305 +#define CSR_MCOUNTEREN 0x306 +#define CSR_MSTATUSH 0x310 + +/* Machine Configuration */ +#define CSR_MENVCFG 0x30a +#define CSR_MENVCFGH 0x31a + +/* Machine Trap Handling */ +#define CSR_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MTVAL 0x343 +#define CSR_MIP 0x344 +#define CSR_MTINST 0x34a +#define CSR_MTVAL2 0x34b + +/* Machine CLIC CSRs */ +#define CSR_MTVT 0x307 +#define CSR_MNXTI 0x345 +#define CSR_MINTSTATUS 0xFB1 +#define CSR_MINTTHRESH 0x347 +#define CSR_MSCRATCHCSW 0x348 +#define CSR_MSCRATCHCSWL 0x349 + +/* Machine Memory Protection */ +#define CSR_PMPCFG0 0x3a0 +#define CSR_PMPCFG1 0x3a1 +#define CSR_PMPCFG2 0x3a2 +#define CSR_PMPCFG3 0x3a3 +#define CSR_PMPCFG4 0x3a4 +#define CSR_PMPCFG5 0x3a5 +#define CSR_PMPCFG6 0x3a6 +#define CSR_PMPCFG7 0x3a7 +#define CSR_PMPCFG8 0x3a8 +#define CSR_PMPCFG9 0x3a9 +#define CSR_PMPCFG10 0x3aa +#define CSR_PMPCFG11 0x3ab +#define CSR_PMPCFG12 0x3ac +#define CSR_PMPCFG13 0x3ad +#define CSR_PMPCFG14 0x3ae +#define CSR_PMPCFG15 0x3af +#define CSR_PMPADDR0 0x3b0 +#define CSR_PMPADDR1 0x3b1 +#define CSR_PMPADDR2 0x3b2 +#define CSR_PMPADDR3 0x3b3 +#define CSR_PMPADDR4 0x3b4 +#define CSR_PMPADDR5 0x3b5 +#define CSR_PMPADDR6 0x3b6 +#define CSR_PMPADDR7 0x3b7 +#define CSR_PMPADDR8 0x3b8 +#define CSR_PMPADDR9 0x3b9 +#define CSR_PMPADDR10 0x3ba +#define CSR_PMPADDR11 0x3bb +#define CSR_PMPADDR12 0x3bc +#define CSR_PMPADDR13 0x3bd +#define CSR_PMPADDR14 0x3be +#define CSR_PMPADDR15 0x3bf +#define CSR_PMPADDR16 0x3c0 +#define CSR_PMPADDR17 0x3c1 +#define CSR_PMPADDR18 0x3c2 +#define CSR_PMPADDR19 0x3c3 +#define CSR_PMPADDR20 0x3c4 +#define CSR_PMPADDR21 0x3c5 +#define CSR_PMPADDR22 0x3c6 +#define CSR_PMPADDR23 0x3c7 +#define CSR_PMPADDR24 0x3c8 +#define CSR_PMPADDR25 0x3c9 +#define CSR_PMPADDR26 0x3ca +#define CSR_PMPADDR27 0x3cb +#define CSR_PMPADDR28 0x3cc +#define CSR_PMPADDR29 0x3cd +#define CSR_PMPADDR30 0x3ce +#define CSR_PMPADDR31 0x3cf +#define CSR_PMPADDR32 0x3d0 +#define CSR_PMPADDR33 0x3d1 +#define CSR_PMPADDR34 0x3d2 +#define CSR_PMPADDR35 0x3d3 +#define CSR_PMPADDR36 0x3d4 +#define CSR_PMPADDR37 0x3d5 +#define CSR_PMPADDR38 0x3d6 +#define CSR_PMPADDR39 0x3d7 +#define CSR_PMPADDR40 0x3d8 +#define CSR_PMPADDR41 0x3d9 +#define CSR_PMPADDR42 0x3da +#define CSR_PMPADDR43 0x3db +#define CSR_PMPADDR44 0x3dc +#define CSR_PMPADDR45 0x3dd +#define CSR_PMPADDR46 0x3de +#define CSR_PMPADDR47 0x3df +#define CSR_PMPADDR48 0x3e0 +#define CSR_PMPADDR49 0x3e1 +#define CSR_PMPADDR50 0x3e2 +#define CSR_PMPADDR51 0x3e3 +#define CSR_PMPADDR52 0x3e4 +#define CSR_PMPADDR53 0x3e5 +#define CSR_PMPADDR54 0x3e6 +#define CSR_PMPADDR55 0x3e7 +#define CSR_PMPADDR56 0x3e8 +#define CSR_PMPADDR57 0x3e9 +#define CSR_PMPADDR58 0x3ea +#define CSR_PMPADDR59 0x3eb +#define CSR_PMPADDR60 0x3ec +#define CSR_PMPADDR61 0x3ed +#define CSR_PMPADDR62 0x3ee +#define CSR_PMPADDR63 0x3ef + +/* Machine Counters/Timers */ +#define CSR_MCYCLE 0xb00 +#define CSR_MINSTRET 0xb02 +#define CSR_MHPMCOUNTER3 0xb03 +#define CSR_MHPMCOUNTER4 0xb04 +#define CSR_MHPMCOUNTER5 0xb05 +#define CSR_MHPMCOUNTER6 0xb06 +#define CSR_MHPMCOUNTER7 0xb07 +#define CSR_MHPMCOUNTER8 0xb08 +#define CSR_MHPMCOUNTER9 0xb09 +#define CSR_MHPMCOUNTER10 0xb0a +#define CSR_MHPMCOUNTER11 0xb0b +#define CSR_MHPMCOUNTER12 0xb0c +#define CSR_MHPMCOUNTER13 0xb0d +#define CSR_MHPMCOUNTER14 0xb0e +#define CSR_MHPMCOUNTER15 0xb0f +#define CSR_MHPMCOUNTER16 0xb10 +#define CSR_MHPMCOUNTER17 0xb11 +#define CSR_MHPMCOUNTER18 0xb12 +#define CSR_MHPMCOUNTER19 0xb13 +#define CSR_MHPMCOUNTER20 0xb14 +#define CSR_MHPMCOUNTER21 0xb15 +#define CSR_MHPMCOUNTER22 0xb16 +#define CSR_MHPMCOUNTER23 0xb17 +#define CSR_MHPMCOUNTER24 0xb18 +#define CSR_MHPMCOUNTER25 0xb19 +#define CSR_MHPMCOUNTER26 0xb1a +#define CSR_MHPMCOUNTER27 0xb1b +#define CSR_MHPMCOUNTER28 0xb1c +#define CSR_MHPMCOUNTER29 0xb1d +#define CSR_MHPMCOUNTER30 0xb1e +#define CSR_MHPMCOUNTER31 0xb1f +#define CSR_MCYCLEH 0xb80 +#define CSR_MINSTRETH 0xb82 +#define CSR_MHPMCOUNTER3H 0xb83 +#define CSR_MHPMCOUNTER4H 0xb84 +#define CSR_MHPMCOUNTER5H 0xb85 +#define CSR_MHPMCOUNTER6H 0xb86 +#define CSR_MHPMCOUNTER7H 0xb87 +#define CSR_MHPMCOUNTER8H 0xb88 +#define CSR_MHPMCOUNTER9H 0xb89 +#define CSR_MHPMCOUNTER10H 0xb8a +#define CSR_MHPMCOUNTER11H 0xb8b +#define CSR_MHPMCOUNTER12H 0xb8c +#define CSR_MHPMCOUNTER13H 0xb8d +#define CSR_MHPMCOUNTER14H 0xb8e +#define CSR_MHPMCOUNTER15H 0xb8f +#define CSR_MHPMCOUNTER16H 0xb90 +#define CSR_MHPMCOUNTER17H 0xb91 +#define CSR_MHPMCOUNTER18H 0xb92 +#define CSR_MHPMCOUNTER19H 0xb93 +#define CSR_MHPMCOUNTER20H 0xb94 +#define CSR_MHPMCOUNTER21H 0xb95 +#define CSR_MHPMCOUNTER22H 0xb96 +#define CSR_MHPMCOUNTER23H 0xb97 +#define CSR_MHPMCOUNTER24H 0xb98 +#define CSR_MHPMCOUNTER25H 0xb99 +#define CSR_MHPMCOUNTER26H 0xb9a +#define CSR_MHPMCOUNTER27H 0xb9b +#define CSR_MHPMCOUNTER28H 0xb9c +#define CSR_MHPMCOUNTER29H 0xb9d +#define CSR_MHPMCOUNTER30H 0xb9e +#define CSR_MHPMCOUNTER31H 0xb9f + +/* Machine Counter Setup */ +#define CSR_MCOUNTINHIBIT 0x320 +#define CSR_MCYCLECFG 0x321 +#define CSR_MINSTRETCFG 0x322 +#define CSR_MHPMEVENT3 0x323 +#define CSR_MHPMEVENT4 0x324 +#define CSR_MHPMEVENT5 0x325 +#define CSR_MHPMEVENT6 0x326 +#define CSR_MHPMEVENT7 0x327 +#define CSR_MHPMEVENT8 0x328 +#define CSR_MHPMEVENT9 0x329 +#define CSR_MHPMEVENT10 0x32a +#define CSR_MHPMEVENT11 0x32b +#define CSR_MHPMEVENT12 0x32c +#define CSR_MHPMEVENT13 0x32d +#define CSR_MHPMEVENT14 0x32e +#define CSR_MHPMEVENT15 0x32f +#define CSR_MHPMEVENT16 0x330 +#define CSR_MHPMEVENT17 0x331 +#define CSR_MHPMEVENT18 0x332 +#define CSR_MHPMEVENT19 0x333 +#define CSR_MHPMEVENT20 0x334 +#define CSR_MHPMEVENT21 0x335 +#define CSR_MHPMEVENT22 0x336 +#define CSR_MHPMEVENT23 0x337 +#define CSR_MHPMEVENT24 0x338 +#define CSR_MHPMEVENT25 0x339 +#define CSR_MHPMEVENT26 0x33a +#define CSR_MHPMEVENT27 0x33b +#define CSR_MHPMEVENT28 0x33c +#define CSR_MHPMEVENT29 0x33d +#define CSR_MHPMEVENT30 0x33e +#define CSR_MHPMEVENT31 0x33f + +/* For RV32 */ +#define CSR_MCYCLECFGH 0x721 +#define CSR_MINSTRETCFGH 0x722 +#define CSR_MHPMEVENT3H 0x723 +#define CSR_MHPMEVENT4H 0x724 +#define CSR_MHPMEVENT5H 0x725 +#define CSR_MHPMEVENT6H 0x726 +#define CSR_MHPMEVENT7H 0x727 +#define CSR_MHPMEVENT8H 0x728 +#define CSR_MHPMEVENT9H 0x729 +#define CSR_MHPMEVENT10H 0x72a +#define CSR_MHPMEVENT11H 0x72b +#define CSR_MHPMEVENT12H 0x72c +#define CSR_MHPMEVENT13H 0x72d +#define CSR_MHPMEVENT14H 0x72e +#define CSR_MHPMEVENT15H 0x72f +#define CSR_MHPMEVENT16H 0x730 +#define CSR_MHPMEVENT17H 0x731 +#define CSR_MHPMEVENT18H 0x732 +#define CSR_MHPMEVENT19H 0x733 +#define CSR_MHPMEVENT20H 0x734 +#define CSR_MHPMEVENT21H 0x735 +#define CSR_MHPMEVENT22H 0x736 +#define CSR_MHPMEVENT23H 0x737 +#define CSR_MHPMEVENT24H 0x738 +#define CSR_MHPMEVENT25H 0x739 +#define CSR_MHPMEVENT26H 0x73a +#define CSR_MHPMEVENT27H 0x73b +#define CSR_MHPMEVENT28H 0x73c +#define CSR_MHPMEVENT29H 0x73d +#define CSR_MHPMEVENT30H 0x73e +#define CSR_MHPMEVENT31H 0x73f + +/* Machine Security Configuration CSR (mseccfg) */ +#define CSR_MSECCFG 0x747 +#define CSR_MSECCFGH 0x757 + +/* Debug/Trace Registers */ +#define CSR_TSELECT 0x7a0 +#define CSR_TDATA1 0x7a1 +#define CSR_TDATA2 0x7a2 +#define CSR_TDATA3 0x7a3 +#define CSR_TINFO 0x7a4 +#define CSR_TCONTROL 0x7a5 +#define CSR_MCONTEXT 0x7a8 + +/* Debug Mode Registers */ +#define CSR_DCSR 0x7b0 +#define CSR_DPC 0x7b1 +#define CSR_DSCRATCH0 0x7b2 +#define CSR_DSCRATCH1 0x7b3 + +/* Machine-Level Window to Indirectly Accessed Registers */ +#define CSR_MISELECT 0x350 +#define CSR_MIREG 0x351 +#define CSR_MIREG2 0x352 +#define CSR_MIREG3 0x353 +#define CSR_MIREG4 0x355 +#define CSR_MIREG5 0x356 +#define CSR_MIREG6 0x357 + +/* Machine-Level Interrupts (AIA) */ +#define CSR_MTOPEI 0x35c +#define CSR_MTOPI 0xfb0 + +/* Virtual Interrupts for Supervisor Level (AIA) */ +#define CSR_MVIEN 0x308 +#define CSR_MVIP 0x309 + +/* Smstateen extension registers */ +/* Machine stateen CSRs */ +#define CSR_MSTATEEN0 0x30C +#define CSR_MSTATEEN0H 0x31C +#define CSR_MSTATEEN1 0x30D +#define CSR_MSTATEEN1H 0x31D +#define CSR_MSTATEEN2 0x30E +#define CSR_MSTATEEN2H 0x31E +#define CSR_MSTATEEN3 0x30F +#define CSR_MSTATEEN3H 0x31F + +/* Machine-Level High-Half CSRs (AIA) */ +#define CSR_MIDELEGH 0x313 +#define CSR_MIEH 0x314 +#define CSR_MVIENH 0x318 +#define CSR_MVIPH 0x319 +#define CSR_MIPH 0x354 + +/* XuanTie custom */ +/* Machine-Level XuanTie custom CSRs */ +#define CSR_MXSTATUS 0x7c0 +#define CSR_MHCR 0x7c1 +#define CSR_MCOR 0x7c2 +#define CSR_MCCR2 0x7c3 +#define CSR_MCER2 0x7c4 +#define CSR_MHINT 0x7c5 +#define CSR_MRMR 0x7c6 +#define CSR_MRVBR 0x7c7 +#define CSR_MCER 0x7c8 +#define CSR_MCOUNTERWEN 0x7c9 +#define CSR_MHINT2 0x7cc +#define CSR_MHINT3 0x7cd +#define CSR_MHINT4 0x7ce +#define CSR_MHPMEVENT0 0x7e0 +#define CSR_MHPMEVENT2 0x7e1 +#define CSR_MHPMCR 0x7f0 +#define CSR_MHPMSR 0x7f1 +#define CSR_MHPMER 0x7f2 +#define CSR_MSMPR 0x7f3 +#define CSR_MZONEID 0x7f5 +#define CSR_MLLCPID 0x7f6 +#define CSR_MLLWP 0x7f7 + +#define CSR_MCINS 0x7d2 +#define CSR_MCINDEX 0x7d3 +#define CSR_MCDATA0 0x7d4 +#define CSR_MCDATA1 0x7d5 +#define CSR_MEICR 0x7d6 +#define CSR_MEICR2 0x7d7 +#define CSR_MBEADDR 0x7d8 + +#define CSR_MCPUID 0xfc0 +#define CSR_MAPBADDR 0xfc1 + +#define CSR_MHALTCAUSE 0xfe0 +#define CSR_MDBGINFO 0xfe1 +#define CSR_MPCFIFO 0xfe2 +#define CSR_MDBGINFO2 0xfe3 + +#define CSR_MNASTATUS 0x8000000000000210 + +#define CSR_MRPLCNTLST 0xbd8 +#define CSR_MCACHELOCK 0xbd9 +#define CSR_MCACHERPLPRI0 0xbda +#define CSR_MCACHERPLPRI1 0xbdb +#define CSR_MCACHERPLPRI2 0xbdc +#define CSR_MCACHERPLPRI3 0xbdd +#define CSR_MCACHERPLPRI4 0xbde +#define CSR_MCACHERPLPRI5 0xbdf + +/* Supervisor-Level XuanTie custom CSRs */ +#define CSR_SXSTATUS 0x5c0 +#define CSR_SHCR 0x5c1 +#define CSR_SCER2 0x5c2 +#define CSR_SCER 0x5c3 +#define CSR_SHINT 0x5c6 +#define CSR_SHINT2 0x5c7 +#define CSR_SHPMINHIBIT 0x5c8 +#define CSR_SHPMCR 0x5c9 +#define CSR_SHPMSR 0x5ca +#define CSR_SHPMER 0x5cb +#define CSR_SL2PID 0x5cc +#define CSR_SL2WP 0x5cd +#define CSR_SBEADDR 0x5d0 +#define CSR_SSBEPA 0x5d1 +#define CSR_SSBEPA2 0x5d2 +#define CSR_SCYCLE 0x5e0 +#define CSR_SINSTRET 0x5e2 +#define CSR_SHPMCOUNTER3 0x5e3 +#define CSR_SHPMCOUNTER4 0x5e4 +#define CSR_SHPMCOUNTER5 0x5e5 +#define CSR_SHPMCOUNTER6 0x5e6 +#define CSR_SHPMCOUNTER7 0x5e7 +#define CSR_SHPMCOUNTER8 0x5e8 +#define CSR_SHPMCOUNTER9 0x5e9 +#define CSR_SHPMCOUNTER10 0x5ea +#define CSR_SHPMCOUNTER11 0x5eb +#define CSR_SHPMCOUNTER12 0x5ec +#define CSR_SHPMCOUNTER13 0x5ed +#define CSR_SHPMCOUNTER14 0x5ee +#define CSR_SHPMCOUNTER15 0x5ef +#define CSR_SHPMCOUNTER16 0x5f0 +#define CSR_SHPMCOUNTER17 0x5f1 +#define CSR_SHPMCOUNTER18 0x5f2 +#define CSR_SHPMCOUNTER19 0x5f3 +#define CSR_SHPMCOUNTER20 0x5f4 +#define CSR_SHPMCOUNTER21 0x5f5 +#define CSR_SHPMCOUNTER22 0x5f6 +#define CSR_SHPMCOUNTER23 0x5f7 +#define CSR_SHPMCOUNTER24 0x5f8 +#define CSR_SHPMCOUNTER25 0x5f9 +#define CSR_SHPMCOUNTER26 0x5fa +#define CSR_SHPMCOUNTER27 0x5fb +#define CSR_SHPMCOUNTER28 0x5fc +#define CSR_SHPMCOUNTER29 0x5fd +#define CSR_SHPMCOUNTER30 0x5fe +#define CSR_SHPMCOUNTER31 0x5ff +#define CSR_SCYCLEH 0x9e0 +#define CSR_SINSTRETH 0x9e2 +#define CSR_SHPMCOUNTER3H 0x9e3 +#define CSR_SHPMCOUNTER4H 0x9e4 +#define CSR_SHPMCOUNTER5H 0x9e5 +#define CSR_SHPMCOUNTER6H 0x9e6 +#define CSR_SHPMCOUNTER7H 0x9e7 +#define CSR_SHPMCOUNTER8H 0x9e8 +#define CSR_SHPMCOUNTER9H 0x9e9 +#define CSR_SHPMCOUNTER10H 0x9ea +#define CSR_SHPMCOUNTER11H 0x9eb +#define CSR_SHPMCOUNTER12H 0x9ec +#define CSR_SHPMCOUNTER13H 0x9ed +#define CSR_SHPMCOUNTER14H 0x9ee +#define CSR_SHPMCOUNTER15H 0x9ef +#define CSR_SHPMCOUNTER16H 0x9f0 +#define CSR_SHPMCOUNTER17H 0x9f1 +#define CSR_SHPMCOUNTER18H 0x9f2 +#define CSR_SHPMCOUNTER19H 0x9f3 +#define CSR_SHPMCOUNTER20H 0x9f4 +#define CSR_SHPMCOUNTER21H 0x9f5 +#define CSR_SHPMCOUNTER22H 0x9f6 +#define CSR_SHPMCOUNTER23H 0x9f7 +#define CSR_SHPMCOUNTER24H 0x9f8 +#define CSR_SHPMCOUNTER25H 0x9f9 +#define CSR_SHPMCOUNTER26H 0x9fa +#define CSR_SHPMCOUNTER27H 0x9fb +#define CSR_SHPMCOUNTER28H 0x9fc +#define CSR_SHPMCOUNTER29H 0x9fd +#define CSR_SHPMCOUNTER30H 0x9fe +#define CSR_SHPMCOUNTER31H 0x9ff + +#define CSR_SRPLCNTLST 0x9d8 +#define CSR_SCACHELOCK 0x9d9 +#define CSR_SCACHERPLPRI0 0x9da +#define CSR_SCACHERPLPRI1 0x9db +#define CSR_SCACHERPLPRI2 0x9dc +#define CSR_SCACHERPLPRI3 0x9dd +#define CSR_SCACHERPLPRI4 0x9de +#define CSR_SCACHERPLPRI5 0x9df + +/* User-Level XuanTie custom CSRs */ +#define CSR_TWCOUNTER 0x804 +#define CSR_FXCR 0x800 +#define CSR_XMRSTART 0x801 +#define CSR_XMCSR 0x802 +#define CSR_XMSIZE 0x803 +#define CSR_XMLENB 0xcc0 +#define CSR_XRLENB 0xcc1 +#define CSR_XMISA 0xcc2 + +#define CSR_URPLCNTLST 0x8e8 +#define CSR_UCACHELOCK 0x8e9 +#define CSR_UCACHERPLPRI0 0x8ea +#define CSR_UCACHERPLPRI1 0x8eb +#define CSR_UCACHERPLPRI2 0x8ec +#define CSR_UCACHERPLPRI3 0x8ed +#define CSR_UCACHERPLPRI4 0x8ee +#define CSR_UCACHERPLPRI5 0x8ef + +#endif /* __CSI_RV_ENCODING_H__ */ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/csi_core.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/csi_core.h new file mode 100644 index 000000000..bbb859ff9 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/csi_core.h @@ -0,0 +1,224 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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) + +#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 \ + || CONFIG_CPU_XUANTIE_E901PLUS_CP || CONFIG_CPU_XUANTIE_E901PLUS_B_CP || CONFIG_CPU_XUANTIE_E901PLUS_M_CP || CONFIG_CPU_XUANTIE_E901PLUS_BM_CP \ + || CONFIG_CPU_XUANTIE_E901_CP || CONFIG_CPU_XUANTIE_E901_B_CP || CONFIG_CPU_XUANTIE_E901_ZM_CP || CONFIG_CPU_XUANTIE_E901_BZM_CP +#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_C908X + return "c908x"; +#elif CONFIG_CPU_XUANTIE_C908X_CP + return "c908x-cp"; +#elif CONFIG_CPU_XUANTIE_C908X_CP_XT + return "c908x-cp-xt"; +#elif CONFIG_CPU_XUANTIE_C910 + return "c910"; +#elif CONFIG_CPU_XUANTIE_C920 + return "c920"; +#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_C910V3_CP_XT + return "c910v3-cp-xt"; +#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_C920V3_CP_XT + return "c920v3-cp-xt"; +#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_R908_CP_XT + return "r908-cp-xt"; +#elif CONFIG_CPU_XUANTIE_R908FD_CP_XT + return "r908fd-cp-xt"; +#elif CONFIG_CPU_XUANTIE_R908FDV_CP_XT + return "r908fdv-cp-xt"; +#elif CONFIG_CPU_XUANTIE_E901PLUS_CP + return "e901plus-cp"; +#elif CONFIG_CPU_XUANTIE_E901PLUS_B_CP + return "e901plusb-cp"; +#elif CONFIG_CPU_XUANTIE_E901PLUS_M_CP + return "e901plusm-cp"; +#elif CONFIG_CPU_XUANTIE_E901PLUS_BM_CP + return "e901plusbm-cp"; +#elif CONFIG_CPU_XUANTIE_E901_CP + return "e901-cp"; +#elif CONFIG_CPU_XUANTIE_E901_B_CP + return "e901b-cp"; +#elif CONFIG_CPU_XUANTIE_E901_ZM_CP + return "e901zm-cp"; +#elif CONFIG_CPU_XUANTIE_E901_BZM_CP + return "e901bzm-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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/clk.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/clk.h new file mode 100755 index 000000000..9e9ee03ed --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/common.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/common.h new file mode 100755 index 000000000..c2c2f84f0 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/common.h @@ -0,0 +1,154 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 DEV_IDX_INVALID 0xFFFFU +#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); +csi_error_t target_get_check_dma_access(uint32_t ctrl_idx, void *srcaddr, void *dstaddr, void **dma_base_src_addr, void **dma_base_dst_addr); +csi_error_t target_get_dma_handshake(uint16_t dma_id, uint16_t dev_id, uint16_t dev_tag, uint8_t type, uint16_t *handshake); +void mdelay(uint32_t ms); +void udelay(uint32_t us); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRV_COMMON_H_ */ + diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/dma.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/dma.h new file mode 100644 index 000000000..7dcf5b5ca --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/dma.h @@ -0,0 +1,306 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_BLOCK_DONE, ///< transfer block done + 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 { + uint16_t ctrl_idx; + uint8_t ch_idx; +} csi_dma_ch_desc_t; + + typedef struct { + uint16_t dev_tag; + uint16_t ctrl_idx; + const csi_dma_ch_desc_t *ch_list; + } csi_dma_ch_spt_list_t; + +typedef struct { + uint16_t ctrl_idx; + uint64_t ch_bit_info; +} csi_dma_ch_bit_desc_t; + + +typedef struct { + uint16_t ctrl_idx; + uint8_t ch_num; +} csi_dma_ch_info_t; + +typedef struct { + uint16_t parent_dev_id; + uint16_t dev_tag; + const csi_dma_ch_bit_desc_t *ch_list; +} csi_dma_ch_bit_spt_list_t; + +#define DMA_HANDSHAKE_NONE 0xff + +typedef enum { + DMA_HANDSHAKE_TYPE_RX = 0x0, + DMA_HANDSHAKE_TYPE_TX = 0x1, +} csi_dma_handshake_type_t; + +typedef struct { + uint16_t parent_dev_id; + uint16_t dev_tag; + uint8_t rx_hs; + uint8_t tx_hs; +} csi_dma_handshake_ctrl_t; + +typedef struct { + uint16_t ctrl_idx; + const csi_dma_handshake_ctrl_t* handshake_ctrl_list; +} csi_dma_handshake_list_t; + +typedef struct { + void* cpu_base_addr; + void* dma_base_addr; + size_t mem_size; +} csi_dma_mem_desc_t; + +typedef struct { + uint16_t ctrl_idx; + const csi_dma_mem_desc_t *mem_list; +} csi_dma_mem_list_t; + +typedef enum { + DMA_LINK_LIST_STOP = 0, + DMA_LINK_LIST_RUNNING, + DMA_LINK_LIST_READY, +} csi_dma_link_list_state_t; + +typedef enum { + DMA_CYCLIC_STOP = 0, + DMA_CYCLIC_RUNNING, + DMA_CYCLIC_READY, +} csi_dma_cyclic_state_t; + +typedef struct { + void *srcaddr; + void *dstaddr; + uint32_t length; +} csi_dma_link_list_item_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 + uint8_t link_list_en; ///< 1:dma enable link list mode, 0: disable + void *lli_buf; ///< link list config +} csi_dma_ch_config_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 + uint16_t group_len; ///< group transaction length (unit: bytes) + uint8_t lli_src_en; ///< 1:dma enable llp, 0 disable + uint8_t lli_dst_en; ///< 1:dma enable llp, 0 disable +} csi_dma_lli_config_t; + +#ifndef DMA_LLI_SIZE +#define DMA_LLI_SIZE 64 +#endif + +#define DEFINE_DESC_BUF(buf_name, num) uint8_t buf_name[num * DMA_LLI_SIZE] __attribute__((aligned(64))); + +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; + csi_dma_trans_dir_t trans_dir; + csi_dma_link_list_state_t link_list_state; + slist_t next; +}; + +typedef struct { + csi_dev_t dev; + slist_t head; + uint64_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 add dma lli + \param[in] dma_ch the dma channel operate handle + \param[in] config lli config + \param[in] item lli + \return csi error code +*/ +csi_error_t csi_dma_add_link_list_item(csi_dma_ch_t *dma_ch, csi_dma_lli_config_t *config, csi_dma_link_list_item_t *item); + +/** + \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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/gpio.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/gpio.h new file mode 100755 index 000000000..fb8aed65c --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/irq.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/irq.h new file mode 100755 index 000000000..6272d15bf --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/list.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/list.h new file mode 100755 index 000000000..9f65050cb --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/pin.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/pin.h new file mode 100755 index 000000000..d1a614b68 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/pin.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 soc.h + * @brief For pin + * @version V1.0 + * @date 11. Mar 2020 + ******************************************************************************/ + +#ifndef _DRV_PIN_H_ +#define _DRV_PIN_H_ + +#include +#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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/porting.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/porting.h new file mode 100755 index 000000000..6ea647a1c --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/tick.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/tick.h new file mode 100755 index 000000000..a5e0a3f18 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/tick.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 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 Get the calendar time in microseconds + \return The absolute timestamp in microseconds since Unix epoch (1970-01-01 00:00:00 UTC) +*/ +uint64_t csi_get_calendar_us(void); + +/** + \brief Set the calendar time in microseconds + \param[in] timestamp The absolute timestamp in microseconds since Unix epoch (1970-01-01 00:00:00 UTC) + \return None +*/ +void csi_set_calendar_us(uint64_t timestamp); + +/** + \brief Increase the sys-tick +*/ +void csi_tick_increase(void); + +#ifdef __cplusplus +} +#endif + +#endif /*_DRV_TICK_H_*/ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/timer.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/timer.h new file mode 100755 index 000000000..9f1039c13 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/uart.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/uart.h new file mode 100755 index 000000000..20ecc29de --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/syslog.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/syslog.h new file mode 100755 index 000000000..063649c8a --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/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/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/src/csi_misc.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/src/csi_misc.c new file mode 100644 index 000000000..f9fd6ee23 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/src/csi_misc.c @@ -0,0 +1,25 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +/* used by csi_mmu_set_mode(If there are multiple mmu modes) */ +int g_mmu_mode = 0; diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/compilers/gcc/sys/ioctl.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/compilers/gcc/sys/ioctl.h new file mode 100644 index 000000000..8ab7ef9a8 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/compilers/gcc/sys/ioctl.h @@ -0,0 +1,46 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __INCLUDE_SYS_IOCTL_H +#define __INCLUDE_SYS_IOCTL_H +#ifdef __cplusplus +extern "C" { +#endif + + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +int ioctl(int fd, int req, ...); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_SYS_IOCTL_H */ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/compilers/gcc/sys/termios.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/compilers/gcc/sys/termios.h new file mode 100644 index 000000000..137d937cc --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/compilers/gcc/sys/termios.h @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2020-2021 Alibaba Group Holding Limited + * A modified version of termios in Haiku OS + * Distributed under the terms of the MIT License. + */ + +#ifndef _SYS_TERMIOS_H_ +#define _SYS_TERMIOS_H_ + +#include + +typedef unsigned long tcflag_t; +typedef unsigned long speed_t; +typedef unsigned char cc_t; + +#define NCCS 12 /* number of control characters */ + +struct termios { + tcflag_t c_iflag; /* input modes */ + tcflag_t c_oflag; /* output modes */ + tcflag_t c_cflag; /* control modes */ + tcflag_t c_lflag; /* local modes */ + cc_t c_cc[NCCS]; /* control characters */ +}; + +/* control characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VEOL 5 +#define VMIN 6 +#define VTIME 7 +#define VEOL2 8 +#define VSTART 9 +#define VSTOP 10 +#define VSUSP 11 + +/* c_iflag - input control modes */ +#define IGNBRK 0x0001 /* ignore break condition */ +#define BRKINT 0x0002 /* break sends interrupt */ +#define IGNPAR 0x0004 /* ignore characters with parity errors */ +#define PARMRK 0x0008 /* mark parity errors */ +#define INPCK 0x0010 /* enable input parity checking */ +#define ISTRIP 0x0020 /* strip high bit from characters */ +#define INLCR 0x0040 /* maps newline to CR on input */ +#define IGNCR 0x0080 /* ignore carriage returns */ +#define ICRNL 0x0100 /* map CR to newline on input */ +#define IUCLC 0x0200 /* map all upper case to lower */ +#define IXON 0x0400 /* enable input SW flow control */ +#define IXANY 0x0800 /* any character will restart input */ +#define IXOFF 0x1000 /* enable output SW flow control */ + +/* c_oflag - output control modes */ +#define OPOST 0x0001 /* enable postprocessing of output */ +#define OLCUC 0x0002 /* map lowercase to uppercase */ +#define ONLCR 0x0004 /* map NL to CR-NL on output */ +#define OCRNL 0x0008 /* map CR to NL on output */ +#define ONOCR 0x0010 /* no CR output when at column 0 */ +#define ONLRET 0x0020 /* newline performs CR function */ +#define OFILL 0x0040 /* use fill characters for delays */ +#define OFDEL 0x0080 /* Fills are DEL, otherwise NUL */ +#define NLDLY 0x0100 /* Newline delays: */ +#define NL0 0x0000 +#define NL1 0x0100 +#define CRDLY 0x0600 /* Carriage return delays: */ +#define CR0 0x0000 +#define CR1 0x0200 +#define CR2 0x0400 +#define CR3 0x0600 +#define TABDLY 0x1800 /* Tab delays: */ +#define TAB0 0x0000 +#define TAB1 0x0800 +#define TAB2 0x1000 +#define TAB3 0x1800 +#define BSDLY 0x2000 /* Backspace delays: */ +#define BS0 0x0000 +#define BS1 0x2000 +#define VTDLY 0x4000 /* Vertical tab delays: */ +#define VT0 0x0000 +#define VT1 0x4000 +#define FFDLY 0x8000 /* Form feed delays: */ +#define FF0 0x0000 +#define FF1 0x8000 + +/* c_cflag - control modes */ +#define CBAUD 0x1000F /* line speed definitions */ +#define B0 0x00 /* hang up */ +#define B50 0x01 /* 50 baud */ +#define B75 0x02 +#define B110 0x03 +#define B134 0x04 +#define B150 0x05 +#define B200 0x06 +#define B300 0x07 +#define B600 0x08 +#define B1200 0x09 +#define B1800 0x0A +#define B2400 0x0B +#define B4800 0x0C +#define B9600 0x0D +#define B19200 0x0E +#define B38400 0x0F +#define CBAUDEX 0x10000 +#define B57600 0x10001 +#define B115200 0x10002 +#define B230400 0x10003 +#define B460800 0x10004 +#define B500000 0x10005 +#define B576000 0x10006 +#define B921600 0x10007 +#define B1000000 0x10008 +#define B1152000 0x10009 +#define B1500000 0x1000A +#define B2000000 0x1000B +#define B2500000 0x1000C +#define B3000000 0x1000D +#define B3500000 0x1000E +#define B4000000 0x1000F +#define CSIZE 0x0030 /* character size */ +#define CS5 0x0000 +#define CS6 0x0010 +#define CS7 0x0020 +#define CS8 0x0030 +#define CSTOPB 0x0040 /* send 2 stop bits, not 1 */ +#define CREAD 0x0080 /* enable receiver */ +#define PARENB 0x0100 /* parity enable */ +#define PARODD 0x0200 /* odd parity, else even */ +#define HUPCL 0x0400 /* hangs up on last close */ +#define CLOCAL 0x0800 /* indicates local line */ +#define XLOBLK 0x1000 /* block layer output? */ +#define CTSFLOW 0x2000 /* enable CTS flow */ +#define RTSFLOW 0x4000 /* enable RTS flow */ +#define CRTSCTS (RTSFLOW | CTSFLOW) + +/* c_lflag - local modes */ +#define ISIG 0x0001 /* enable signals */ +#define ICANON 0x0002 /* Canonical input */ +#define XCASE 0x0004 /* Canonical u/l case */ +#define ECHO 0x0008 /* Enable echo */ +#define ECHOE 0x0010 /* Echo erase as bs-sp-bs */ +#define ECHOK 0x0020 /* Echo nl after kill */ +#define ECHONL 0x0040 /* Echo nl */ +#define NOFLSH 0x0080 /* Disable flush after int or quit */ +#define TOSTOP 0x0100 /* stop bg processes that write to tty */ +#define IEXTEN 0x0200 /* implementation defined extensions */ +#define ECHOCTL 0x0400 +#define ECHOPRT 0x0800 +#define ECHOKE 0x1000 +#define FLUSHO 0x2000 +#define PENDIN 0x4000 + +/* options to tcsetattr() */ +#define TCSANOW 0x01 /* make change immediate */ +#define TCSADRAIN 0x02 /* drain output, then change */ +#define TCSAFLUSH 0x04 /* drain output, flush input */ + +/* actions for tcflow() */ +#define TCOOFF 0x01 /* suspend output */ +#define TCOON 0x02 /* restart output */ +#define TCIOFF 0x04 /* transmit STOP character, intended to stop input data */ +#define TCION 0x08 /* transmit START character, intended to resume input data */ + +/* values for tcflush() */ +#define TCIFLUSH 0x01 /* flush pending input */ +#define TCOFLUSH 0x02 /* flush untransmitted output */ +#define TCIOFLUSH 0x03 /* flush both */ + +#define cfmakeraw(termios) \ + do { \ + (termios)->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | \ + INLCR | IGNCR | ICRNL | IXON); \ + (termios)->c_oflag &= ~OPOST; \ + (termios)->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); \ + (termios)->c_cflag &= ~(CSIZE | PARENB); \ + (termios)->c_cflag |= CS8; \ + } while (0) + +#define cfsetspeed(termios, speed) \ + ({ \ + tcflag_t flag; \ + int ret = 0; \ + switch (speed) { \ + case 0: \ + flag = B0; \ + break; \ + case 50: \ + flag = B50; \ + break; \ + case 75: \ + flag = B75; \ + break; \ + case 110: \ + flag = B110; \ + break; \ + case 134: \ + flag = B134; \ + break; \ + case 150: \ + flag = B150; \ + break; \ + case 200: \ + flag = B200; \ + break; \ + case 300: \ + flag = B300; \ + break; \ + case 600: \ + flag = B600; \ + break; \ + case 1200: \ + flag = B1200; \ + break; \ + case 1800: \ + flag = B1800; \ + break; \ + case 2400: \ + flag = B2400; \ + break; \ + case 4800: \ + flag = B4800; \ + break; \ + case 9600: \ + flag = B9600; \ + break; \ + case 19200: \ + flag = B19200; \ + break; \ + case 38400: \ + flag = B38400; \ + break; \ + case 57600: \ + flag = B57600; \ + break; \ + case 115200: \ + flag = B115200; \ + break; \ + case 230400: \ + flag = B230400; \ + break; \ + case 460800: \ + flag = B460800; \ + break; \ + case 500000: \ + flag = B500000; \ + break; \ + case 576000: \ + flag = B576000; \ + break; \ + case 921600: \ + flag = B921600; \ + break; \ + case 1000000: \ + flag = B1000000; \ + break; \ + case 1152000: \ + flag = B1152000; \ + break; \ + case 1500000: \ + flag = B1500000; \ + break; \ + case 2000000: \ + flag = B2000000; \ + break; \ + case 2500000: \ + flag = B2500000; \ + break; \ + case 3000000: \ + flag = B3000000; \ + break; \ + case 3500000: \ + flag = B3500000; \ + break; \ + case 4000000: \ + flag = B4000000; \ + break; \ + default: \ + ret = -1; \ + break; \ + } \ + if (ret) { \ + errno = EINVAL; \ + } else { \ + (termios)->c_cflag &= ~CBAUD; \ + (termios)->c_cflag |= flag; \ + } \ + ret; \ + }) + +#endif /* _SYS_TERMIOS_H_ */ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/compilers/gcc/time.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/compilers/gcc/time.h new file mode 100644 index 000000000..febb819e3 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/compilers/gcc/time.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. 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 __INCLUDE_TIME_H +#define __INCLUDE_TIME_H + +/******************************************************************************** + * Included Files + ********************************************************************************/ +#include +#include +#include +#include +#include + +/******************************************************************************** + * Pre-processor Definitions + ********************************************************************************/ + +/* Clock tick of the system (frequency Hz). + * + * NOTE: This symbolic name CLK_TCK has been removed from the standard. It is + * replaced with CLOCKS_PER_SEC. Both are defined here. + * + * The default value is 100Hz + */ +# define CLK_TCK (1000000) +# define CLOCKS_PER_SEC (1000000) + +#define NSEC_PER_SEC 1000000000 +#define USEC_PER_SEC 1000000 +#define NSEC_PER_USEC 1000 +#define USEC_PER_MSEC 1000 +#define MSEC_PER_SEC 1000 +#define NSEC_PER_MSEC 1000000 +#define TICK2MSEC(tick) ((tick)* (1000 / CLOCKS_PER_SEC)) + +extern long timezone; + +/* CLOCK_REALTIME refers to the standard time source. For most + * implementations, the standard time source is the system timer interrupt. + * However, if the platform supports an RTC, then the standard time source + * will be the RTC for the clock_gettime() and clock_settime() interfaces + * (the system timer is still the time source for all of the interfaces). + * + * CLOCK_REALTIME represents the machine's best-guess as to the current + * wall-clock, time-of-day time. This means that CLOCK_REALTIME can jump + * forward and backward as the system time-of-day clock is changed. + */ + +#define CLOCK_REALTIME 0 + +/* Clock that cannot be set and represents monotonic time since some + * unspecified starting point. It is not affected by changes in the + * system time-of-day clock. + */ +#define CLOCK_MONOTONIC 1 + +/* This is a flag that may be passed to the timer_settime() function */ + +#define TIMER_ABSTIME 1 + +/* Local time is the same as gmtime in this implementation */ +// # define localtime(c) gmtime(c) +// # define localtime_r(c,r) gmtime_r(c,r) + +/******************************************************************************** + * Public Types + ********************************************************************************/ +/* Scalar types */ + +// #ifndef _TIME_T_DECLARED +// #define _TIME_T_DECLARED +// typedef int32_t time_t; /* Holds time in seconds */ +// #endif + + +// #ifndef _CLOCK_T_DECLARED +// #define _CLOCK_T_DECLARED +// typedef uint32_t clock_t; +// #endif + +/* struct tm is the standard representation for "broken out" time. + * + * REVISIT: This structure could be packed better using uint8_t's and + * uint16_t's. The standard definition does, however, call out type int for + * all of the members. NOTE: Any changes to this structure must be also be + * reflected in struct rtc_time defined in include/nuttx/timers/rtc.h; these + * two structures must be cast compatible. + */ + +struct tm +{ + int tm_sec; /* Seconds (0-61, allows for leap seconds) */ + int tm_min; /* Minutes (0-59) */ + int tm_hour; /* Hours (0-23) */ + int tm_mday; /* Day of the month (1-31) */ + int tm_mon; /* Month (0-11) */ + int tm_year; /* Years since 1900 */ + int tm_wday; /* Day of the week (0-6) */ + int tm_yday; /* Day of the year (0-365) */ + int tm_isdst; /* Non-0 if daylight savings time is in effect */ +}; + +/* forward reference (defined in signal.h) */ + +struct sigevent; + +/******************************************************************************** + * Public Data + ********************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/******************************************************************************** + * Public Function Prototypes + ********************************************************************************/ +int clock_settime(clockid_t clockid, const struct timespec *tp); +int clock_gettime(clockid_t clockid, struct timespec *tp); + +time_t mktime(struct tm *tp); +struct tm *gmtime(const time_t *timep); +struct tm *gmtime_r(const time_t *timep, struct tm *result); +struct tm *localtime (const time_t *timep); +struct tm *localtime_r(const time_t *timep, struct tm *result); + +size_t strftime( char *s, size_t max, const char *format, + const struct tm *tm); + +char *ctime( const time_t *timep); + +time_t time( time_t *timep); + +clock_t clock(void); + +double difftime(time_t tim1, time_t tim2); +char *asctime(const struct tm *tim_p); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_TIME_H */ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/errno.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/errno.h new file mode 100644 index 000000000..0c280ce2e --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/errno.h @@ -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. + */ + +/****************************************************************************** + * @file errno.h + * @brief header file for error num + * @version V1.0 + * @date 02. June 2017 + ******************************************************************************/ +#ifndef __ERRNO_H__ +#define __ERRNO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************************************************************** + * Error Number Definitions + ****************************************************************************/ +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ + +/* + * This error code is special: arch syscall entry code will return + * -ENOSYS if users try to call a syscall that doesn't exist. To keep + * failures of syscalls that really do exist distinguishable from + * failures due to attempts to use a nonexistent syscall, syscall + * implementations should refrain from returning -ENOSYS. + */ +#define ENOSYS 38 /* Invalid system call number */ + +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define ECANCELED 125 /* Operation Canceled */ +#define ENOKEY 126 /* Required key not available */ +#define EKEYEXPIRED 127 /* Key has expired */ +#define EKEYREVOKED 128 /* Key has been revoked */ +#define EKEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +#define ERFKILL 132 /* Operation not possible due to RF-kill */ + +#define EHWPOISON 133 /* Memory page has hardware error */ + +#define ENOTSUP 134 /* Not supported */ + +extern int errno; + +#ifdef __cplusplus +} +#endif + +#endif /* __ERRNO_H__ */ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/inttypes.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/inttypes.h new file mode 100644 index 000000000..cd8b619af --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/inttypes.h @@ -0,0 +1,57 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 _PRIV_INTTYPES_H_ +#define _PRIV_INTTYPES_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#include_next + +#undef PRId32 +#undef PRIi32 +#undef PRIo32 +#undef PRIu32 +#undef PRIx32 +#undef PRIX32 + +#undef SCNd32 +#undef SCNi32 +#undef SCNo32 +#undef SCNu32 +#undef SCNx32 + +#define PRId32 __STRINGIFY(d) +#define PRIi32 __STRINGIFY(i) +#define PRIo32 __STRINGIFY(o) +#define PRIu32 __STRINGIFY(u) +#define PRIx32 __STRINGIFY(x) +#define PRIX32 __STRINGIFY(X) + +#define SCNd32 __STRINGIFY(d) +#define SCNi32 __STRINGIFY(i) +#define SCNo32 __STRINGIFY(o) +#define SCNu32 __STRINGIFY(u) +#define SCNx32 __STRINGIFY(x) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/serf/minilibc_stdio.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/serf/minilibc_stdio.h new file mode 100644 index 000000000..67b6bb40f --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/serf/minilibc_stdio.h @@ -0,0 +1,85 @@ +/* + * minilibc stdio + * + * Copyright (C): 2012 Hangzhou C-SKY Microsystem Co.,LTD. + * Author: Junshan Hu (junshan_hu@c-sky.com) + * Contrbutior: Chunqiang Li + * Date: 2012-5-4 + */ + +#ifndef _MINILIBC_STDIO_H_ +#define _MINILIBC_STDIO_H_ + +#include + +#define BUFSIZE 2048 + +struct __stdio_file { + int fd; + int flags; + unsigned int bs; /* read: bytes in buffer */ + unsigned int bm; /* position in buffer */ +// unsigned int buflen; /* length of buf */ +// char *buf; + struct __stdio_file *next; /* for fflush */ + unsigned char ungetbuf; + char ungotten; + unsigned int lock; +}; + +#define ERRORINDICATOR 1 +#define EOFINDICATOR 2 +#define BUFINPUT 4 +#define BUFLINEWISE 8 +#define NOBUF 16 +#define STATICBUF 32 +#define FDPIPE 64 +#define CANREAD 128 +#define CANWRITE 256 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*fmt_out_fn)(char * strbuf, int len); +typedef int (*fmt_in_fn)(void); +extern fmt_out_fn g_current_outputs; +extern fmt_in_fn g_current_inputs; +#define print_current_out_set(fn) do{g_current_outputs = fn;}while(0) +#define print_current_in_set(fn) do{g_current_inputs = fn;}while(0) +static inline int is_normal_outputs(void) +{ + if(g_current_inputs) + return 0; + return 1; +} + +/* ..scanf */ +struct arg_scanf { + void *data; + int (*getch)(void*); + int (*putch)(int,void*); +}; + +int __v_scanf(struct arg_scanf* fn, const char *format, va_list arg_ptr); + +struct arg_printf { + void *data; + int (*put)(void*,size_t,void*); +}; + +int yoc__v_printf(struct arg_printf* fn, const char *format, va_list arg_ptr); +int __isinf(double d); +int __isnan(double d); +int __dtostr(double d,char *buf,unsigned int maxlen,unsigned int prec,unsigned int prec2); +int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase); +int __ltostr(char *s, unsigned int size, unsigned long i, unsigned int base, int UpCase); + + +#ifdef __cplusplus +} +#endif + +#endif /* _MINILIBC_STDIO_H_ */ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/_stdint.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/_stdint.h new file mode 100644 index 000000000..88d8fe4d6 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/_stdint.h @@ -0,0 +1,45 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 _PRIV_STDINT_H_ +#define _PRIV_STDINT_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#if __STDC_HOSTED__ +/* For newlib and minilibc utint32_t are not same */ +#undef _UINT32_T_DECLARED +#define _UINT32_T_DECLARED +typedef unsigned int uint32_t; + +#undef _INT32_T_DECLARED +#define _INT32_T_DECLARED +typedef signed int int32_t; + +#endif /* __STDC_HOSTED__ */ + +#define IN_ADDR_T_DEFINED + +#include_next + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/random.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/random.h new file mode 100644 index 000000000..bce4b7f74 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/random.h @@ -0,0 +1,34 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __SYS_RANDOM__ +#define __SYS_RANDOM__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +ssize_t getrandom(void *buf, size_t buflen, unsigned int flags); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif //__SYS_RANDOM__ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/select.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/select.h new file mode 100644 index 000000000..56f479c3d --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/select.h @@ -0,0 +1,52 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 __SYS_SELECT_H +#define __SYS_SELECT_H + +#include + +#ifndef FD_SETSIZE +#define FD_SETSIZE 1024 +#endif + +typedef unsigned long fd_mask; +typedef struct { + unsigned long fds_bits[FD_SETSIZE / 8 / sizeof(long)]; +} fd_set; + +#define FD_ZERO(s) memset((void*)(s), 0, sizeof(*(s))) +#define FD_SET(d, s) ((s)->fds_bits[(d) / (8 * sizeof(long))] |= (1UL << ((d) % (8 * sizeof(long))))) +#define FD_CLR(d, s) ((s)->fds_bits[(d) / (8 * sizeof(long))] &= ~(1UL << ((d) % (8 * sizeof(long))))) +#define FD_ISSET(d, s) (!!((s)->fds_bits[(d) / (8 * sizeof(long))] & (1UL << ((d) % (8 * sizeof(long)))))) + +#ifdef __cplusplus +extern "C" { +#endif + +int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, + struct timeval *timeout); + +extern int select2(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout, void *semaphore); + +#ifdef __cplusplus +} +#endif + +#endif /*__SYS_SELECT_H*/ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/time.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/time.h new file mode 100644 index 000000000..0e4ed9d51 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/include/sys/time.h @@ -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. + */ + +#ifndef __INCLUDE_SYS_TIME_H +#define __INCLUDE_SYS_TIME_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _TIME_T_DECLARED +#define _TIME_T_DECLARED +typedef int32_t time_t; +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ +#ifndef _TIMEVAL_DEFINED +#define _TIMEVAL_DEFINED +/* struct timeval represents time as seconds plus microseconds */ + +struct timeval +{ + time_t tv_sec; /* Seconds */ + long tv_usec; /* Microseconds */ +}; +#endif + +/* The use of the struct timezone is obsolete; the tz argument should + * normally be specified as NULL (and is ignored in any event). + */ + +struct timezone +{ + int tz_minuteswest; /* Minutes west of Greenwich */ + int tz_dsttime; /* Type of DST correction */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: gettimeofday + * + * Description: + * Get the current time + * + * Conforming to SVr4, 4.3BSD. POSIX.1-2001 describes gettimeofday(). + * POSIX.1-2008 marks gettimeofday() as obsolete, recommending the use of + * clock_gettime(2) instead. + * + * NuttX implements gettimeofday() as a thin layer around clock_gettime(); + * + * Input Parameters: + * tv - The location to return the current time + * tz - Ignored + * + * Returned value: + * Zero (OK) on success; -1 is returned on failure with the errno variable + * set appropriately. + * + ****************************************************************************/ + +int gettimeofday( struct timeval *tv, struct timezone *tz); + +/**************************************************************************** + * Name: settimeofday + * + * Description: + * Set the current time + * + * Conforming to SVr4, 4.3BSD. POSIX.1-2001 describes gettimeofday() but + * not settimeofday(). + * + * NuttX implements settimeofday() as a thin layer around clock_settime(); + * + * Input Parameters: + * tv - The net to time to be set + * tz - Ignored + * + * Returned value: + * Zero (OK) on success; -1 is returned on failure with the errno variable + * set appropriately. + * + ****************************************************************************/ + +int settimeofday( const struct timeval *tv, const struct timezone *tz); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_SYS_TIME_H */ diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/mini_printf.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/mini_printf.c new file mode 100644 index 000000000..e1aea6e64 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/mini_printf.c @@ -0,0 +1,947 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. These routines are thread +// safe and reentrant! +// Use this instead of the bloated standard/newlib printf cause these use +// malloc for printf (and may not be thread safe). +// +/////////////////////////////////////////////////////////////////////////////// + +#if CONFIG_LIBC_MINI_PRINTF_SUPPORT +#include +#include +#include + +#include +#include +#include +#include +#include + + +// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the +// printf_config.h header file +// default: undefined +#ifdef PRINTF_INCLUDE_CONFIG_H +#include "printf_config.h" +#endif + + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +// support for the floating point type (%f) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +// support for exponential floating point notation (%e/%g) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL +#define PRINTF_SUPPORT_EXPONENTIAL +#endif + +// define the default floating point precision +// default: 6 digits +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +// define the largest float suitable to print with %f +// default: 1e9 +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +// support for the long long types (%llu or %p) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +// support for the ptrdiff_t type (%t) +// ptrdiff_t is normally defined in as long or long long type +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + + +// import float.h for DBL_MAX +#if defined(PRINTF_SUPPORT_FLOAT) +#include +#endif + +extern csi_uart_t g_console_handle; + +static void _putchar(char character) +{ + if (character == '\n') { + csi_uart_putc(&g_console_handle, '\r'); + } + + csi_uart_putc(&g_console_handle, character); +} + +// output function type +typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); + + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void* arg); + void* arg; +} out_fct_wrap_type; + + +// internal buffer output +static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) +{ + if (idx < maxlen) { + ((char*)buffer)[idx] = character; + } +} + + +// internal null output +static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)character; + (void)buffer; + (void)idx; + (void)maxlen; +} + + +// internal _putchar wrapper +static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)buffer; + (void)idx; + (void)maxlen; + if (character) { + _putchar(character); + } +} + + +// internal output function wrapper +static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)idx; + (void)maxlen; + if (character) { + // buffer is the output fct pointer + ((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg); + } +} + + +// internal secure strlen +// \return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int _strnlen_s(const char* str, size_t maxsize) +{ + const char* s; + for (s = str; *s && maxsize--; ++s); + return (unsigned int)(s - str); +} + + +// internal test if char is a digit (0-9) +// \return true if char is a digit +static inline bool _is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + + +// internal ASCII string to unsigned int conversion +static unsigned int _atoi(const char** str) +{ + unsigned int i = 0U; + while (_is_digit(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + + +// output the specified string in reverse, taking care of any zero-padding +static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) +{ + const size_t start_idx = idx; + + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + + +// internal itoa format +static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) +{ + // pad leading zeros + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + // handle hash + if (flags & FLAGS_HASH) { + if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { + len--; + if (len && (base == 16U)) { + len--; + } + } + if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_NTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +// internal itoa for 'long' type +static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} + + +// internal itoa for 'long long' type +#if defined(PRINTF_SUPPORT_LONG_LONG) +static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#endif // PRINTF_SUPPORT_LONG_LONG + + +#if defined(PRINTF_SUPPORT_FLOAT) + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags); +#endif + + +// internal ftoa for fixed decimal floating point +static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + + // powers of 10 + static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + + // test for special values + if (value != value) + return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + // test for very large values + // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad + if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); +#else + return 0U; +#endif + } + + // test for negative + bool negative = false; + if (value < 0) { + negative = true; + value = 0 - value; + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + // limit precision to 9, cause a prec >= 10 can lead to overflow errors + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { + buf[len++] = '0'; + prec--; + } + + int whole = (int)value; + double tmp = (value - whole) * pow10[prec]; + unsigned long frac = (unsigned long)tmp; + diff = tmp - frac; + + if (diff > 0.5) { + ++frac; + // handle rollover, e.g. case 0.99 with prec 1 is 1.0 + if (frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } else if (diff < 0.5) { + } else if ((frac == 0U) || (frac & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++frac; + } + + if (prec == 0U) { + diff = value - (double)whole; + if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++whole; + } + } else { + unsigned int count = prec; + // now do fractional part, as an unsigned number + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(48U + (frac % 10U)); + if (!(frac /= 10U)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + // add decimal + buf[len++] = '.'; + } + } + + // do whole part, number is reversed + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(48 + (whole % 10)); + if (!(whole /= 10)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + // check for NaN and special values + if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { + return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); + } + + // determine the sign + const bool negative = value < 0; + if (negative) { + value = -value; + } + + // default precision + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // determine the decimal exponent + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + union { + uint64_t U; + double F; + } conv; + + conv.F = value; + int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 + conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) + // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 + int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^expval but we want to be sure it won't overflow + exp2 = (int)(expval * 3.321928094887362 + 0.5); + const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = (uint64_t)(exp2 + 1023) << 52U; + // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if (value < conv.F) { + expval--; + conv.F /= 10; + } + + // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters + unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; + + // in "%g" mode, "prec" is the number of *significant figures* not decimals + if (flags & FLAGS_ADAPT_EXP) { + // do we want to fall-back to "%f" mode? + if ((value >= 1e-4) && (value < 1e6)) { + if ((int)prec > expval) { + prec = (unsigned)((int)prec - expval - 1); + } else { + prec = 0; + } + flags |= FLAGS_PRECISION; // make sure _ftoa respects precision + // no characters in exponent + minwidth = 0U; + expval = 0; + } else { + // we use one sigfig for the whole part + if ((prec > 0) && (flags & FLAGS_PRECISION)) { + --prec; + } + } + } + + // will everything fit? + unsigned int fwidth = width; + if (width > minwidth) { + // we didn't fall-back so subtract the characters required for the exponent + fwidth -= minwidth; + } else { + // not enough characters, so go back to default sizing + fwidth = 0U; + } + if ((flags & FLAGS_LEFT) && minwidth) { + // if we're padding on the right, DON'T pad the floating part + fwidth = 0U; + } + + // rescale the float value + if (expval) { + value /= conv.F; + } + + // output the floating part + const size_t start_idx = idx; + idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); + + // output the exponent part + if (minwidth) { + // output the exponential symbol + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + // output the exponent value + idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS); + // might need to right-pad spaces + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + + +// internal vsnprintf +static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) +{ + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + // use null output function + out = _out_null; + } + + while (*format) { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': + flags |= FLAGS_ZEROPAD; + format++; + n = 1U; + break; + case '-': + flags |= FLAGS_LEFT; + format++; + n = 1U; + break; + case '+': + flags |= FLAGS_PLUS; + format++; + n = 1U; + break; + case ' ': + flags |= FLAGS_SPACE; + format++; + n = 1U; + break; + case '#': + flags |= FLAGS_HASH; + format++; + n = 1U; + break; + default : + n = 0U; + break; + } + } while (n); + + // evaluate width field + width = 0U; + if (_is_digit(*format)) { + width = _atoi(&format); + } else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (_is_digit(*format)) { + precision = _atoi(&format); + } else if (*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l' : + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h' : + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't' : + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j' : + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z' : + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default : + break; + } + + // evaluate specifier + switch (*format) { + case 'd' : + case 'i' : + case 'u' : + case 'x' : + case 'X' : + case 'o' : + case 'b' : { + // set the base + unsigned int base; + if (*format == 'x' || *format == 'X') { + base = 16U; + } else if (*format == 'o') { + base = 8U; + } else if (*format == 'b') { + base = 2U; + } else { + base = 10U; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); +#endif + } else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + } else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags); +#endif + } else if (flags & FLAGS_LONG) { + idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags); + } else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); + idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f' : + case 'F' : + if (*format == 'F') flags |= FLAGS_UPPERCASE; + idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + case 'c' : { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's' : { + const char* p = va_arg(va, char*); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p' : { + width = sizeof(void*) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + const bool is_ll = sizeof(uintptr_t) == sizeof(long long); + if (is_ll) { + idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags); + } else { +#endif + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%' : + out('%', buffer, idx++, maxlen); + format++; + break; + + default : + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + + +/////////////////////////////////////////////////////////////////////////////// + +int printf(const char* format, ...) +{ + va_list va; + va_start(va, format); + char buffer[1]; + const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + +int fprintf(FILE *stream, const char* format, ...) +{ + + va_list va; + va_start(va, format); + char buffer[1]; + const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + + +int sprintf(char* buffer, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + +int snprintf(char* buffer, size_t count, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); + va_end(va); + return ret; +} + + +int vprintf(const char* format, va_list va) +{ + char buffer[1]; + return _vsnprintf(_out_char, buffer, (size_t)-1, format, va); +} + + +int vsnprintf(char* buffer, size_t count, const char* format, va_list va) +{ + return _vsnprintf(_out_buffer, buffer, count, format, va); +} + + +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) +{ + va_list va; + va_start(va, format); + const out_fct_wrap_type out_fct_wrap = { out, arg }; + const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va); + va_end(va); + return ret; +} +#endif + diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/newlib_stub.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/newlib_stub.c new file mode 100644 index 000000000..593d85721 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/libc_threadx/newlib_stub.c @@ -0,0 +1,317 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +extern csi_uart_t g_console_handle; + +int _execve_r(struct _reent *ptr, const char *name, char *const *argv, + char *const *env) +{ + ptr->_errno = ENOSYS; + return -1; +} + +int _fcntl_r(struct _reent *ptr, int fd, int cmd, int arg) +{ + ptr->_errno = EBADF; + return -1; +} + +int _fork_r(struct _reent *ptr) +{ + ptr->_errno = ENOSYS; + return -1; +} + +int _getpid_r(struct _reent *ptr) +{ + ptr->_errno = ENOSYS; + return 0; +} + +int _isatty_r(struct _reent *ptr, int fd) +{ + if (fd >= 0 && fd < 3) { + return 1; + } + + ptr->_errno = ENOTTY; + return 0; +} + +int _kill_r(struct _reent *ptr, int pid, int sig) +{ + ptr->_errno = ENOSYS; + return -1; +} + +_off_t _lseek_r(struct _reent *ptr, int fd, _off_t pos, int whence) +{ + ptr->_errno = ENOSYS; + return -1; +} + +int _mkdir_r(struct _reent *ptr, const char *name, int mode) +{ + ptr->_errno = ENOSYS; + return -1; +} + +int _open_r(struct _reent *ptr, const char *file, int flags, int mode) +{ + ptr->_errno = ENOSYS; + return -1; +} + +int _close_r(struct _reent *ptr, int fd) +{ + ptr->_errno = EBADF; + return -1; +} + +_ssize_t _read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes) +{ + ptr->_errno = EBADF; + return -1; +} + +int fputc(int ch, FILE *stream) +{ + if (ch == '\n') { + csi_uart_putc(&g_console_handle, '\r'); + } + + csi_uart_putc(&g_console_handle, ch); + return 0; +} + +int fgetc(FILE *stream) +{ + (void)stream; + + return csi_uart_getc(&g_console_handle); +} + +int putc(int c, FILE *stream) +{ + return fputc(c, stream); +} + +int puts(const char *s) +{ + while(*s !='\0') { + fputc(*s, (void *)-1); + s++; + } + fputc('\n', (void *)-1); + return 0; +} + +static void _putchar(char character) +{ + if (character == '\n') { + csi_uart_putc(&g_console_handle, '\r'); + } + + csi_uart_putc(&g_console_handle, character); + +} + +int putchar(int c) +{ + _putchar(c); + return 0; +} + +_ssize_t _write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes) +{ + if ((fd == STDOUT_FILENO) || (fd == STDERR_FILENO)) { + for (int i = 0; i < nbytes; i++) + _putchar((*((char*)buf + i))); + return nbytes; + } else { + return -1; + } +} + +int ioctl(int fildes, int request, ... /* arg */) +{ + return -1; +} + +int _rename_r(struct _reent *ptr, const char *oldname, const char *newname) +{ + ptr->_errno = ENOSYS; + return -1; +} + +void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr) +{ + ptr->_errno = ENOSYS; + return NULL; +} + +int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat) +{ + ptr->_errno = ENOSYS; + return -1; +} + +int _fstat_r(struct _reent *ptr, int fd, struct stat *buf) +{ + ptr->_errno = EBADF; + return -1; +} + +_CLOCK_T_ _times_r(struct _reent *ptr, struct tms *ptms) +{ + ptr->_errno = ENOSYS; + return -1; +} + +int _link_r(struct _reent *ptr, const char *oldpath, const char *newpath) +{ + ptr->_errno = ENOSYS; + return -1; +} + +int _unlink_r(struct _reent *ptr, const char *file) +{ + ptr->_errno = ENOSYS; + return -1; +} + +int _wait_r(struct _reent *ptr, int *status) +{ + ptr->_errno = ENOSYS; + return -1; +} + +int _gettimeofday_r(struct _reent *ptr, struct timeval *tv, void *__tzp) +{ + return 0; +} + +long timezone = 8; /* default CTS */ + +struct tm* localtime_r(const time_t* t, struct tm* r) +{ + time_t time_tmp; + time_tmp = *t + timezone * 3600; + return gmtime_r(&time_tmp, r); +} + +struct tm* localtime(const time_t* t) +{ + struct tm* timeinfo; + static struct tm tm_tmp; + + timeinfo = localtime_r(t, &tm_tmp); + + return timeinfo; +} + +extern TX_BYTE_POOL tx_byte_pool_0; +void *_malloc_r(struct _reent *ptr, size_t size) +{ + UINT ret; + void *p; + + ret = tx_byte_allocate(&tx_byte_pool_0, &p, size, TX_NO_WAIT); + if(ret != TX_SUCCESS) { + return NULL; + } + return p; +} + +void *_realloc_r(struct _reent *ptr, void *old, size_t newlen) +{ + return NULL; +} + +void *_calloc_r(struct _reent *ptr, size_t size, size_t len) +{ + UINT ret; + void *p; + + ret = tx_byte_allocate(&tx_byte_pool_0, &p, size * len, TX_NO_WAIT); + if(ret != TX_SUCCESS) { + return NULL; + } + memset(p, 0, size * len); + + return p; +} + +void *_memalign_r(struct _reent *ptr, size_t alignment, size_t size) +{ + return NULL; +} + +void _free_r(struct _reent *ptr, void *addr) +{ + if (!addr) + return; + tx_byte_release(addr); +} + +void _exit(int status) +{ + while (1) + ; +} + +void exit(int status) +{ + __builtin_unreachable(); // fix noreturn warning +} + +__attribute__((weak)) void _fini() +{ +} + +void _system(const char *s) +{ + return; +} + +void abort(void) +{ + __builtin_unreachable(); // fix noreturn warning +} + +int isatty(int fd) +{ + if (fd == fileno(stdin) || fd == fileno(stdout) || fd == fileno(stderr)) { + return -1; + } + return 0; +} + diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/demo_threadx.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/demo_threadx.c new file mode 100644 index 000000000..5f17f954e --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/demo_threadx.c @@ -0,0 +1,372 @@ +/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight + threads of different priorities, using a message queue, semaphore, mutex, event flags group, + byte pool, and block pool. */ + +#include +#include "tx_api.h" + +#define DEMO_STACK_SIZE 1024 +#define DEMO_BYTE_POOL_SIZE 9120 +#define DEMO_BLOCK_POOL_SIZE 100 +#define DEMO_QUEUE_SIZE 100 + + +/* Define the ThreadX object control blocks... */ + +TX_THREAD thread_0; +TX_THREAD thread_1; +TX_THREAD thread_2; +TX_THREAD thread_3; +TX_THREAD thread_4; +TX_THREAD thread_5; +TX_THREAD thread_6; +TX_THREAD thread_7; +TX_QUEUE queue_0; +TX_SEMAPHORE semaphore_0; +TX_MUTEX mutex_0; +TX_EVENT_FLAGS_GROUP event_flags_0; +TX_BYTE_POOL byte_pool_0; +TX_BLOCK_POOL block_pool_0; +UCHAR memory_area[DEMO_BYTE_POOL_SIZE]; + + +/* Define the counters used in the demo application... */ + +ULONG thread_0_counter; +ULONG thread_1_counter; +ULONG thread_1_messages_sent; +ULONG thread_2_counter; +ULONG thread_2_messages_received; +ULONG thread_3_counter; +ULONG thread_4_counter; +ULONG thread_5_counter; +ULONG thread_6_counter; +ULONG thread_7_counter; + + +/* Define thread prototypes. */ + +void thread_0_entry(ULONG thread_input); +void thread_1_entry(ULONG thread_input); +void thread_2_entry(ULONG thread_input); +void thread_3_and_4_entry(ULONG thread_input); +void thread_5_entry(ULONG thread_input); +void thread_6_and_7_entry(ULONG thread_input); + + +/* Define main entry point. */ + +int main() +{ + + /* Enter the ThreadX kernel. */ + tx_kernel_enter(); +} + + +/* Define what the initial system looks like. */ + +void tx_application_define(void *first_unused_memory) +{ + +CHAR *pointer = TX_NULL; + + + /* Create a byte memory pool from which to allocate the thread stacks. */ + tx_byte_pool_create(&byte_pool_0, "byte pool 0", memory_area, DEMO_BYTE_POOL_SIZE); + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + /* Allocate the stack for thread 0. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create the main thread. */ + tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, DEMO_STACK_SIZE, + 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START); + + + /* Allocate the stack for thread 1. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 1 and 2. These threads pass information through a ThreadX + message queue. It is also interesting to note that these threads have a time + slice. */ + tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, DEMO_STACK_SIZE, + 16, 16, 4, TX_AUTO_START); + + /* Allocate the stack for thread 2. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, DEMO_STACK_SIZE, + 16, 16, 4, TX_AUTO_START); + + /* Allocate the stack for thread 3. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore. + An interesting thing here is that both threads share the same instruction area. */ + tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 4. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 5. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create thread 5. This thread simply pends on an event flag which will be set + by thread_0. */ + tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, DEMO_STACK_SIZE, + 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 6. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 6 and 7. These threads compete for a ThreadX mutex. */ + tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 7. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the message queue. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT); + + /* Create the message queue shared by threads 1 and 2. */ + tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG)); + + /* Create the semaphore used by threads 3 and 4. */ + tx_semaphore_create(&semaphore_0, "semaphore 0", 1); + + /* Create the event flags group used by threads 1 and 5. */ + tx_event_flags_create(&event_flags_0, "event flags 0"); + + /* Create the mutex used by thread 6 and 7 without priority inheritance. */ + tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + + /* Allocate the memory for a small block pool. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT); + + /* Create a block memory pool to allocate a message buffer from. */ + tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE); + + /* Allocate a block and release the block memory. */ + tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT); + + /* Release the block back to the pool. */ + tx_block_release(pointer); +} + + + +/* Define the test threads. */ + +void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* This thread simply sits in while-forever-sleep loop. */ + while(1) + { + puts("[Thread] : thread_0_entry is here!"); + /* Increment the thread counter. */ + thread_0_counter++; + + /* Sleep for 10 ticks. */ + tx_thread_sleep(10); + + /* Set event flag 0 to wakeup thread 5. */ + status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} + + +void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + /* This thread simply sends messages to a queue shared by thread 2. */ + while(1) + { + puts("[Thread] : thread_1_entry is here!"); + /* Increment the thread counter. */ + thread_1_counter++; + + /* Send message to queue 0. */ + status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER); + + /* Check completion status. */ + if (status != TX_SUCCESS) + break; + + /* Increment the message sent. */ + thread_1_messages_sent++; + } +} + + +void thread_2_entry(ULONG thread_input) +{ + +ULONG received_message; +UINT status; + + /* This thread retrieves messages placed on the queue by thread 1. */ + while(1) + { + puts("[Thread] : thread_2_entry is here!"); + /* Increment the thread counter. */ + thread_2_counter++; + + /* Retrieve a message from the queue. */ + status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER); + + /* Check completion status and make sure the message is what we + expected. */ + if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received)) + break; + + /* Otherwise, all is okay. Increment the received message count. */ + thread_2_messages_received++; + } +} + + +void thread_3_and_4_entry(ULONG thread_input) +{ + +UINT status; + + + /* This function is executed from thread 3 and thread 4. As the loop + below shows, these function compete for ownership of semaphore_0. */ + while(1) + { + puts("[Thread] : thread_3_and_4_entry is here!"); + + /* Increment the thread counter. */ + if (thread_input == 3) + thread_3_counter++; + else + thread_4_counter++; + + /* Get the semaphore with suspension. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Sleep for 2 ticks to hold the semaphore. */ + tx_thread_sleep(2); + + /* Release the semaphore. */ + status = tx_semaphore_put(&semaphore_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} + + +void thread_5_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_flags; + + + /* This thread simply waits for an event in a forever loop. */ + while(1) + { + puts("[Thread] : thread_5_entry is here!"); + /* Increment the thread counter. */ + thread_5_counter++; + + /* Wait for event flag 0. */ + status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR, + &actual_flags, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_flags != 0x1)) + break; + } +} + + +void thread_6_and_7_entry(ULONG thread_input) +{ + +UINT status; + + + /* This function is executed from thread 6 and thread 7. As the loop + below shows, these function compete for ownership of mutex_0. */ + while(1) + { + puts("[Thread] : thread_6_and_7_entry is here!"); + /* Increment the thread counter. */ + if (thread_input == 6) + thread_6_counter++; + else + thread_7_counter++; + + /* Get the mutex with suspension. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Get the mutex again with suspension. This shows + that an owning thread may retrieve the mutex it + owns multiple times. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Sleep for 2 ticks to hold the mutex. */ + tx_thread_sleep(2); + + /* Release the mutex. */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Release the mutex again. This will actually + release ownership since it was obtained twice. */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/gdbinit b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/gdbinit new file mode 100644 index 000000000..1042ec781 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/gdbinit @@ -0,0 +1 @@ +target remote localhost:1234 \ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/pre_main.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/pre_main.c new file mode 100644 index 000000000..7227633d5 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/pre_main.c @@ -0,0 +1,27 @@ + /* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 + +extern int main(); + +void pre_main(void) +{ + board_init(); + main(); +} \ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/readme_e906.txt b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/readme_e906.txt new file mode 100644 index 000000000..2ffd76181 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/readme_e906.txt @@ -0,0 +1,236 @@ + Eclipse Foundation's RTOS, ThreadX for XuanTie E906 + + Using the GNU Tools + +The XuanTie E906 is a fully synthesizable, middle-end, microcontroller-class processor that is compatible to the RISC-V RV32IMA[F][D]C[P] ISA. It +delivers considerable integer and enhanced, energy-efficient floating-point compute performance especially the double precision. + +1. Building the ThreadX run-time Library + +Prerequisites +- Install a XuanTie bare-metal GNU toolchain with riscv64-unknown-elf prefix +- Download URL: https://www.xrvm.cn/community/download?versionId=4460156621967921152 +- Toolchain archive name: XuanTie-900-gcc-elf-newlib-x86_64-V3.2.0-20250627.tar.gz + +Verify the toolchain: + riscv64-unknown-elf-gcc --version + riscv64-unknown-elf-objdump --version + +Library build script + build_libthreadx.sh + +Example build script + +The example demonstration contains a build script. See: + + build_threadx_sample.sh + +This script builds the library and the demo application demo_threadx.elf. + + +2. Demonstration System (QEMU) + +Prerequisites +- Install a XuanTie QEMU +- Download URL: https://www.xrvm.cn/community/download?versionId=4468398114511851520 +- QEMU archive name: XuanTie-qemu-x86_64-Ubuntu-20.04-V5.2.8-B20250721-0303.tar.gz + +The provided example is targeted at XuanTie QEMU's smartl platform. After building the +example, the produced demo_threadx.elf can be executed in QEMU: + + qemu-system-riscv32 -nographic -machine smartl -cpu e906fdp -kernel demo_threadx.elf + +Typical QEMU features used: +- Single-core CPU +- UART serial console +- CLIC (Core-Local Interrupt Controller) + +3. System Initialization + +Entry Point + +The example startup code begins at the Reset_Handler label in startup.S. This startup +code performs hardware initialization including: +- Initialize gp register +- Set up the entry for interrupt and exception handler +- Set up initial stack pointer +- Jump to SystemInit() for initialize CLIC、Clear BSS、Cache、System Clock、System Tick +- Jump to pre_main() + +In pre_main(), the following initialization is performed: +Board Initialization (board_init.c) +- Initialize UART + +Then jump to main(). + +4. Interrupt Handling + +Machine Mode Operation + +ThreadX operates in machine mode (M-mode), the highest privilege level. +All interrupts and exceptions trap to machine mode. + +Interrupt Sources + +1. Machine Timer Interrupt (MTI): + - Triggered by CLINT when mtime >= mtimecmp + - Handled by _tx_timer_interrupt (src/tx_timer_interrupt.c) + - Called from tick_irq_handler() in example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/tick.c + +2. External Interrupts (MEI): + - Routed through CLIC + - Handled by do_irq() in example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/src/sys/irq.c + +3. Software Interrupts (MSI): + - Routed through CLIC + - Handled by tspend_handler() in src/tx_thread_context.S + +Interrupt Control Macros + +TX_DISABLE and TX_RESTORE macros atomically manage the MIE bit in mstatus: + + TX_DISABLE: Saves and clears MIE bit via csrrci (CSR read-clear immediate) + TX_RESTORE: Restores only MIE bit via csrrs (CSR read-set) + Other mstatus bits remain unchanged + +These are defined in ports/xuantie/e906/gnu/inc/tx_port.h and use the +_tx_thread_interrupt_control() function. + + +5. Thread Scheduling and Context Switching + +Fist Thread Switch (src/tx_thread_schedule.S) +1. Enables interrupts while waiting a thread +2. Spins until _tx_thread_execute_ptr becomes non-NULL +3. Disables interrupts (critical section) +4. Sets _tx_thread_current_ptr = _tx_thread_execute_ptr +5. Increments thread's run count +6. Switches to thread's stack +7. Restores the thread's context, then returns via mret + +Thread Scheduler (src/tx_thread_system_return.S, src/tx_thread_context.S) +1. Set a software interrupt to trigger context switch +2. Come to software interrupt handler (tspend_handler) +3. Save previous thread's context +4. Check and waiting for _tx_thread_execute_ptr != NULL +5. Switch thread sp to _tx_thread_execute_ptr +6. Restores the thread's context, then returns via mret + +Initial Thread Stack Frame (src/tx_thread_stack_build.S) + +New threads start with a fake interrupt frame containing: +- All registers initialized to 0 +- ra (x1) = _tx_thread_exit +- mepc = entry function pointer +- mstatus = mstatus.FS=1 | mstatus.MPP=3 | mstatus.MPIE=1 +- Floating-point registers initialized based on ABI + + +6. Port Configuration and Macros + +Default Configurations (in ports/risc-v64/gnu/inc/tx_port.h): + + TX_MINIMUM_STACK 1024 /* Minimum thread stack size */ + TX_TIMER_THREAD_STACK_SIZE 1024 /* Timer thread stack size */ + TX_TIMER_THREAD_PRIORITY 0 /* Timer thread priority */ + TX_MAX_PRIORITIES 32 /* Must be multiple of 32 */ + +These can be overridden in tx_user.h or on the compiler command line. + + +7. Build Configuration + +CMake Toolchain File: example_build/xuantie_smartl_fpga/xuantie_e906_gnu.cmake + +Compiler Flags: + -mcpu=e906fdp RISC-V RV32IMA[F][D]C[P] + -mcmodel=medlow ±2GB addressability + -D__ASSEMBLER__ For assembly files + + +8. File Organization + +Example files (example_build/xuantie_smartl_fpga/): + - components/chip_riscv_dummy/src/arch/e906fdp Startup code, Interrupt handlers + - components/chip_riscv_dummy/src/drivers The basic peripheral drivers for the platform + - components/chip_riscv_dummy/src/sys System initialization + - components/chip_riscv_dummy/gcc_flash_smartl.ld Linker script for QEMU smartl + - components/csi CPU core and peripheral API + - components/libc_threadx Minimum printf and malloc implementation + - boards/board_riscv_dummy/src Bsp initialization + - pre_main.c Call main function + - tx_user.h ThreadX user defines + - build_libthreadx.sh Build script + + +9. Linker Script Requirements + +The linker script must provide: + +1. Entry point: + ENTRY(Reset_Handler) + +2. Memory layout: + - .text section (code) + - .rodata section (read-only data) + - .data section (initialized data) + - .bss section (uninitialized data) + +3. Symbols: + - __data_start__, __data_end__: For data copy from Flash when executed in DRAM + - __bss_start__, __bss_end__: For zero initialization + - __heap_start, __heap_end: For ThreadX allocation memory + +4. Alignment: + - 4-byte alignment throughout + +10. Performance and Debugging + +Performance Optimization + +Build optimizations: +- Use -O2 or -O3 for production (example uses -O0 for debugging) +- Enable -Wl,--gc-sections to remove unused code +- Define TX_DISABLE_ERROR_CHECKING to remove parameter checks +- Consider -flto for link-time optimization + +Debugging with QEMU and GDB + +Start QEMU in debug mode: + qemu-system-riscv32 -nographic -machine smartl -cpu e906fdp -kernel demo_threadx.elf -s -S + + -s: Enable GDB server on TCP port 1234 + -S: Pause at startup waiting for GDB + +Connect GDB: + riscv64-unknown-elf-gdb demo_threadx.elf + (gdb) target remote :1234 + (gdb) break main + (gdb) continue + +Useful GDB commands: + (gdb) info registers # View general registers + (gdb) info all-registers # Include CSR and FP registers + (gdb) p/x $mstatus # View machine status register + (gdb) x/32gx $sp # Examine stack memory + (gdb) p *_tx_thread_current_ptr # View current thread control block + + +11. Platform-Specific Notes (QEMU smartl) +See https://www.xrvm.com/soft-tools/tools/QEMU + +Timer frequency is platform-dependent (example uses 100MHz). + + +12. Revision History + +For generic code revision information, refer to ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/readme_e906.txt. + +The following details the revision history for this xuantie/e906 GNU port: + +12-02-2026 Steven Lin Support XuanTie E906 + + +Copyright (c) 1996-2026 Microsoft Corporation + +https://azure.com/rtos diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/tx_user.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/tx_user.h new file mode 100644 index 000000000..896e2233e --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/tx_user.h @@ -0,0 +1,370 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** User Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_user.h PORTABLE C */ +/* 6.3.0 */ +/* */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains user defines for configuring ThreadX in specific */ +/* ways. This file will have an effect only if the application and */ +/* ThreadX library are built with TX_INCLUDE_USER_DEFINE_FILE defined. */ +/* Note that all the defines in this file may also be made on the */ +/* command line when building ThreadX library and application objects. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 William E. Lamie Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* 03-02-2021 Scott Larson Modified comment(s), */ +/* added option to remove */ +/* FileX pointer, */ +/* resulting in version 6.1.5 */ +/* 06-02-2021 Scott Larson Added options for multiple */ +/* block pool search & delay, */ +/* resulting in version 6.1.7 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), added */ +/* user-configurable symbol */ +/* TX_TIMER_TICKS_PER_SECOND */ +/* resulting in version 6.1.9 */ +/* 04-25-2022 Wenhui Xie Modified comment(s), */ +/* optimized the definition of */ +/* TX_TIMER_TICKS_PER_SECOND, */ +/* resulting in version 6.1.11 */ +/* 10-31-2023 Xiuwen Cai Modified comment(s), */ +/* added option for random */ +/* number stack filling, */ +/* resulting in version 6.3.0 */ +/* */ +/**************************************************************************/ + +#ifndef TX_USER_H +#define TX_USER_H + +#ifndef __ASSEMBLY__ +/* define extra stack size */ +#if __riscv_matrix || __riscv_xtheadmatrix +static inline int _csi_xmlenb_get_value(void) +{ + int result; + __asm volatile("csrr %0, xmlenb" : "=r"(result) : : "memory"); + return result; +} +#define STACK_M_EXTRAL_SIZE (_csi_xmlenb_get_value() * 8 + 24) +#else +#define STACK_M_EXTRAL_SIZE 0 +#endif /* __riscv_matrix || __riscv_xtheadmatrix */ + +#ifdef __riscv_vector +static inline int _csi_vlenb_get_value(void) +{ + int result; + __asm volatile("csrr %0, vlenb" : "=r"(result) : : "memory"); + return result; +} + +#define STACK_V_EXTRAL_SIZE (_csi_vlenb_get_value() * 32 + 40) +#else +#define STACK_V_EXTRAL_SIZE 0 +#endif /* __riscv_vector */ + +#ifdef __riscv_flen +#define STACK_F_EXTRAL_SIZE (__riscv_flen / 8 * 32 + 8) +#else +#define STACK_F_EXTRAL_SIZE 0 +#endif /*__riscv_flen*/ + +#define CSK_CPU_STACK_EXTRAL (STACK_M_EXTRAL_SIZE + STACK_V_EXTRAL_SIZE + STACK_F_EXTRAL_SIZE) + +#ifndef STATIC_CSK_CPU_STACK_EXTRAL +#if defined(__riscv_matrix) || defined(__riscv_xtheadmatrix) || defined(__riscv_vector) +/* FIXME: for static allocate stack */ +#define STATIC_CSK_CPU_STACK_EXTRAL (8192) +#else +#define STATIC_CSK_CPU_STACK_EXTRAL (0) +#endif +#endif /* STATIC_CSK_CPU_STACK_EXTRAL */ + +#endif /* __ASSEMBLY__ */ + +/* Define various build options for the ThreadX port. The application should either make changes + here by commenting or un-commenting the conditional compilation defined OR supply the defines + though the compiler's equivalent of the -D option. + + For maximum speed, the following should be defined: + + TX_MAX_PRIORITIES 32 + TX_DISABLE_PREEMPTION_THRESHOLD + TX_DISABLE_REDUNDANT_CLEARING + TX_DISABLE_NOTIFY_CALLBACKS + TX_NOT_INTERRUPTABLE + TX_TIMER_PROCESS_IN_ISR + TX_REACTIVATE_INLINE + TX_DISABLE_STACK_FILLING + TX_INLINE_THREAD_RESUME_SUSPEND + + For minimum size, the following should be defined: + + TX_MAX_PRIORITIES 32 + TX_DISABLE_PREEMPTION_THRESHOLD + TX_DISABLE_REDUNDANT_CLEARING + TX_DISABLE_NOTIFY_CALLBACKS + TX_NO_FILEX_POINTER + TX_NOT_INTERRUPTABLE + TX_TIMER_PROCESS_IN_ISR + + Of course, many of these defines reduce functionality and/or change the behavior of the + system in ways that may not be worth the trade-off. For example, the TX_TIMER_PROCESS_IN_ISR + results in faster and smaller code, however, it increases the amount of processing in the ISR. + In addition, some services that are available in timers are not available from ISRs and will + therefore return an error if this option is used. This may or may not be desirable for a + given application. */ + + +/* Override various options with default values already assigned in tx_port.h. Please also refer + to tx_port.h for descriptions on each of these options. */ + +#define TX_MAX_PRIORITIES 32 +#define TX_MINIMUM_STACK (512 + CSK_CPU_STACK_EXTRAL) +#define TX_TIMER_THREAD_STACK_SIZE (512 + STATIC_CSK_CPU_STACK_EXTRAL) +/* +#define TX_MAX_PRIORITIES 32 +#define TX_MINIMUM_STACK ???? +#define TX_THREAD_USER_EXTENSION ???? +#define TX_TIMER_THREAD_STACK_SIZE ???? +#define TX_TIMER_THREAD_PRIORITY ???? +*/ + +/* Define the common timer tick reference for use by other middleware components. The default + value is 10ms (i.e. 100 ticks, defined in tx_api.h), but may be replaced by a port-specific + version in tx_port.h or here. + Note: the actual hardware timer value may need to be changed (usually in tx_initialize_low_level). */ + +#ifdef CONFIG_SYSTICK_HZ +#define TX_TIMER_TICKS_PER_SECOND CONFIG_SYSTICK_HZ +#else +#define TX_TIMER_TICKS_PER_SECOND 100 +#endif +/* +#define TX_TIMER_TICKS_PER_SECOND (100UL) +*/ + +/* Determine if there is a FileX pointer in the thread control block. + By default, the pointer is there for legacy/backwards compatibility. + The pointer must also be there for applications using FileX. + Define this to save space in the thread control block. +*/ + +/* +#define TX_NO_FILEX_POINTER +*/ + +/* Determine if timer expirations (application timers, timeouts, and tx_thread_sleep calls + should be processed within the a system timer thread or directly in the timer ISR. + By default, the timer thread is used. When the following is defined, the timer expiration + processing is done directly from the timer ISR, thereby eliminating the timer thread control + block, stack, and context switching to activate it. */ + +/* +#define TX_TIMER_PROCESS_IN_ISR +*/ + +/* Determine if in-line timer reactivation should be used within the timer expiration processing. + By default, this is disabled and a function call is used. When the following is defined, + reactivating is performed in-line resulting in faster timer processing but slightly larger + code size. */ + +/* +#define TX_REACTIVATE_INLINE +*/ + +/* Determine is stack filling is enabled. By default, ThreadX stack filling is enabled, + which places an 0xEF pattern in each byte of each thread's stack. This is used by + debuggers with ThreadX-awareness and by the ThreadX run-time stack checking feature. */ + +/* +#define TX_DISABLE_STACK_FILLING +*/ + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +/* +#define TX_ENABLE_STACK_CHECKING +*/ + +/* Determine if random number is used for stack filling. By default, ThreadX uses a fixed + pattern for stack filling. When the following is defined, ThreadX uses a random number + for stack filling. This is effective only when TX_ENABLE_STACK_CHECKING is defined. */ + +/* +#define TX_ENABLE_RANDOM_NUMBER_STACK_FILLING +*/ + +/* Determine if preemption-threshold should be disabled. By default, preemption-threshold is + enabled. If the application does not use preemption-threshold, it may be disabled to reduce + code size and improve performance. */ + +/* +#define TX_DISABLE_PREEMPTION_THRESHOLD +*/ + +/* Determine if global ThreadX variables should be cleared. If the compiler startup code clears + the .bss section prior to ThreadX running, the define can be used to eliminate unnecessary + clearing of ThreadX global variables. */ + +/* +#define TX_DISABLE_REDUNDANT_CLEARING +*/ + +/* Determine if no timer processing is required. This option will help eliminate the timer + processing when not needed. The user will also have to comment out the call to + tx_timer_interrupt, which is typically made from assembly language in + tx_initialize_low_level. Note: if TX_NO_TIMER is used, the define TX_TIMER_PROCESS_IN_ISR + must also be used and tx_timer_initialize must be removed from ThreadX library. */ + +/* +#define TX_NO_TIMER +#ifndef TX_TIMER_PROCESS_IN_ISR +#define TX_TIMER_PROCESS_IN_ISR +#endif +*/ + +/* Determine if the notify callback option should be disabled. By default, notify callbacks are + enabled. If the application does not use notify callbacks, they may be disabled to reduce + code size and improve performance. */ + +/* +#define TX_DISABLE_NOTIFY_CALLBACKS +*/ + + +/* Determine if the tx_thread_resume and tx_thread_suspend services should have their internal + code in-line. This results in a larger image, but improves the performance of the thread + resume and suspend services. */ + +/* +#define TX_INLINE_THREAD_RESUME_SUSPEND +*/ + + +/* Determine if the internal ThreadX code is non-interruptable. This results in smaller code + size and less processing overhead, but increases the interrupt lockout time. */ + +/* +#define TX_NOT_INTERRUPTABLE +*/ + + +/* Determine if the trace event logging code should be enabled. This causes slight increases in + code size and overhead, but provides the ability to generate system trace information which + is available for viewing in TraceX. */ + +/* +#define TX_ENABLE_EVENT_TRACE +*/ + + +/* Determine if block pool performance gathering is required by the application. When the following is + defined, ThreadX gathers various block pool performance information. */ + +/* +#define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if byte pool performance gathering is required by the application. When the following is + defined, ThreadX gathers various byte pool performance information. */ + +/* +#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if event flags performance gathering is required by the application. When the following is + defined, ThreadX gathers various event flags performance information. */ + +/* +#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if mutex performance gathering is required by the application. When the following is + defined, ThreadX gathers various mutex performance information. */ + +/* +#define TX_MUTEX_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if queue performance gathering is required by the application. When the following is + defined, ThreadX gathers various queue performance information. */ + +/* +#define TX_QUEUE_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if semaphore performance gathering is required by the application. When the following is + defined, ThreadX gathers various semaphore performance information. */ + +/* +#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if thread performance gathering is required by the application. When the following is + defined, ThreadX gathers various thread performance information. */ + +/* +#define TX_THREAD_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if timer performance gathering is required by the application. When the following is + defined, ThreadX gathers various timer performance information. */ + +/* +#define TX_TIMER_ENABLE_PERFORMANCE_INFO +*/ + +/* Override options for byte pool searches of multiple blocks. */ + +/* +#define TX_BYTE_POOL_MULTIPLE_BLOCK_SEARCH 20 +*/ + +/* Override options for byte pool search delay to avoid thrashing. */ + +/* +#define TX_BYTE_POOL_DELAY_VALUE 3 +*/ + +#endif + diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/xuantie_e906_gnu.cmake b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/xuantie_e906_gnu.cmake new file mode 100644 index 000000000..b724b0d7e --- /dev/null +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/xuantie_e906_gnu.cmake @@ -0,0 +1,15 @@ +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR xuantie_e906) + +set(THREADX_ARCH "xuantie_e906") +set(THREADX_TOOLCHAIN "gnu") +set(ARCH_FLAGS "-g -mcpu=e906fd -mcmodel=medlow") +set(CFLAGS "${ARCH_FLAGS}") +set(ASFLAGS "${ARCH_FLAGS}") +set(LDFLAGS "${ARCH_FLAGS}") + +set(TX_USER_FILE ${CMAKE_CURRENT_LIST_DIR}/tx_user.h) +set(THREADX_CUSTOM_PORT ${CMAKE_CURRENT_LIST_DIR}/../../) + +include(${CMAKE_CURRENT_LIST_DIR}/../../../../../cmake/riscv64-unknown-elf.cmake) \ No newline at end of file diff --git a/ports/risc-v32/gnu/inc/tx_port.h b/ports/risc-v32/gnu/inc/tx_port.h new file mode 100644 index 000000000..f4dd75afe --- /dev/null +++ b/ports/risc-v32/gnu/inc/tx_port.h @@ -0,0 +1,291 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port.h RISC-V32/GNU */ +/* 6.4.x */ +/* */ +/* AUTHOR */ +/* */ +/* Akif Ejaz, 10xEngineers */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the ThreadX */ +/* real-time kernel function identically on a variety of different */ +/* processor architectures. For example, the size or number of bits */ +/* in an "int" data type vary between microprocessor architectures and */ +/* even C compilers for the same microprocessor. ThreadX does not */ +/* directly use native C data types. Instead, ThreadX creates its */ +/* own special types that can be mapped to actual data types by this */ +/* file to guarantee consistency in the interface and functionality. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 23-12-2025 Akif Ejaz Initial Version 6.4.x */ +/* */ +/**************************************************************************/ + +#ifndef TX_PORT_H +#define TX_PORT_H + +#ifndef __ASSEMBLER__ + +/* Include for memset. */ +#include + + +/* Determine if the optional ThreadX user define file should be used. */ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in tx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "tx_user.h" +#endif /* TX_INCLUDE_USER_DEFINE_FILE */ + +#endif /* __ASSEMBLER__ */ + + +/* Define ThreadX basic types for this port. */ + +#define VOID void + +#ifndef __ASSEMBLER__ +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned long long ULONG64; +typedef short SHORT; +typedef unsigned short USHORT; +#define ULONG64_DEFINED +#endif /* __ASSEMBLER__ */ + + + + +/* Define the priority levels for ThreadX. Legal values range + from 32 to 1024 and MUST be evenly divisible by 32. */ + +#ifndef TX_MAX_PRIORITIES +#define TX_MAX_PRIORITIES 32 +#endif + + +/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during + thread creation is less than this value, the thread create call will return an error. */ + +#ifndef TX_MINIMUM_STACK +#define TX_MINIMUM_STACK 1024 /* Minimum stack size for this port */ +#endif + + +/* Define the system timer thread's default stack size and priority. These are only applicable + if TX_TIMER_PROCESS_IN_ISR is not defined. */ + +#ifndef TX_TIMER_THREAD_STACK_SIZE +#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */ +#endif + +#ifndef TX_TIMER_THREAD_PRIORITY +#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */ +#endif + + +/* Define various constants for the ThreadX RISC-V port. */ + +#define TX_INT_DISABLE 0x00000000 /* Disable interrupts value */ +#define TX_INT_ENABLE 0x00000008 /* Enable interrupt value */ + + +/* Define the clock source for trace event entry time stamp. The following two item are port specific. + For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock + source constants would be: + +#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024) +#define TX_TRACE_TIME_MASK 0x0000FFFFUL + +*/ + +#ifndef TX_TRACE_TIME_SOURCE +#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time +#endif +#ifndef TX_TRACE_TIME_MASK +#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL +#endif + + +/* Define the port specific options for the _tx_build_options variable. This variable indicates + how the ThreadX library was built. */ + +#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0 + + +/* Define the in-line initialization constant so that modules with in-line + initialization capabilities can prevent their initialization from being + a function call. */ + +#define TX_INLINE_INITIALIZATION + + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +#ifdef TX_ENABLE_STACK_CHECKING +#undef TX_DISABLE_STACK_FILLING +#endif + + +/* Define the TX_THREAD control block extensions for this port. The main reason + for the multiple macros is so that backward compatibility can be maintained with + existing ThreadX kernel awareness modules. */ + +#define TX_THREAD_EXTENSION_0 +#define TX_THREAD_EXTENSION_1 +#define TX_THREAD_EXTENSION_2 +#define TX_THREAD_EXTENSION_3 + + +/* Define the port extensions of the remaining ThreadX objects. */ + +#define TX_BLOCK_POOL_EXTENSION +#define TX_BYTE_POOL_EXTENSION +#define TX_EVENT_FLAGS_GROUP_EXTENSION +#define TX_MUTEX_EXTENSION +#define TX_QUEUE_EXTENSION +#define TX_SEMAPHORE_EXTENSION +#define TX_TIMER_EXTENSION + + +/* Define the user extension field of the thread control block. Nothing + additional is needed for this port so it is defined as white space. */ + +#ifndef TX_THREAD_USER_EXTENSION +#define TX_THREAD_USER_EXTENSION +#endif + + +/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete, + tx_thread_shell_entry, and tx_thread_terminate. */ + +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + + +/* Define the ThreadX object creation extensions for the remaining objects. */ + +#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr) +#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr) +#define TX_QUEUE_CREATE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr) +#define TX_TIMER_CREATE_EXTENSION(timer_ptr) + + +/* Define the ThreadX object deletion extensions for the remaining objects. */ + +#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr) +#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr) +#define TX_QUEUE_DELETE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr) +#define TX_TIMER_DELETE_EXTENSION(timer_ptr) + + +/* Define ThreadX interrupt lockout and restore macros for protection on + access of critical kernel information. The restore interrupt macro must + restore the interrupt posture of the running thread prior to the value + present prior to the disable macro. In most cases, the save area macro + is used to define a local function save area for the disable and restore + macros. */ + +/* Expose helper used to perform an atomic read/modify/write of mstatus. + The helper composes and returns the posture per ThreadX contract. */ +#ifndef __ASSEMBLER__ +UINT _tx_thread_interrupt_control(UINT new_posture); +#endif + +#ifdef TX_DISABLE_INLINE + +#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; + +#define TX_DISABLE __asm__ volatile("csrrci %0, mstatus, 8" : "=r" (interrupt_save) :: "memory"); +#define TX_RESTORE { \ + unsigned long _temp_mstatus; \ + __asm__ volatile( \ + "csrc mstatus, 8\n" \ + "andi %0, %1, 8\n" \ + "csrs mstatus, %0" \ + : "=&r" (_temp_mstatus) \ + : "r" (interrupt_save) \ + : "memory"); \ + } + +#else + +#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE); +#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save); + +#endif /* TX_DISABLE_INLINE */ + + +/* Define the interrupt lockout macros for each ThreadX object. */ + +#define TX_BLOCK_POOL_DISABLE TX_DISABLE +#define TX_BYTE_POOL_DISABLE TX_DISABLE +#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE +#define TX_MUTEX_DISABLE TX_DISABLE +#define TX_QUEUE_DISABLE TX_DISABLE +#define TX_SEMAPHORE_DISABLE TX_DISABLE + + +/* Define the version ID of ThreadX. This may be utilized by the application. */ + +#ifndef __ASSEMBLER__ +#ifdef TX_THREAD_INIT +CHAR _tx_version_id[] = + "Copyright (c) 2024 Microsoft Corporation. * ThreadX RISC-V32/GNU Version 6.4.2 *"; +#else +extern CHAR _tx_version_id[]; +#endif /* TX_THREAD_INIT */ +#endif /* __ASSEMBLER__ */ + +#endif /* TX_PORT_H */ \ No newline at end of file diff --git a/ports/risc-v32/gnu/readme_threadx.txt b/ports/risc-v32/gnu/readme_threadx.txt new file mode 100644 index 000000000..e4f16971f --- /dev/null +++ b/ports/risc-v32/gnu/readme_threadx.txt @@ -0,0 +1,432 @@ + Eclipse Foundation's RTOS, ThreadX for RISC-V32 + + Using the GNU Tools + + +1. Building the ThreadX run-time Library + +Prerequisites +- Install a RISC-V32 bare-metal GNU toolchain with riscv32-unknown-elf prefix +- Common source: https://github.com/riscv-collab/riscv-gnu-toolchain + +Verify the toolchain: + riscv32-unknown-elf-gcc --version + riscv32-unknown-elf-objdump --version + +CMake-based build (recommended) + +From the ThreadX top-level directory: + + cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/riscv32_gnu.cmake . + cmake --build ./build/ + +This uses cmake/riscv32_gnu.cmake and ports/risc-v32/gnu/CMakeLists.txt to +configure the cross-compiler flags and produce the ThreadX run-time library +and example binaries. + +Example build script + +The example demonstration contains a build script. See: + + ports/risc-v32/gnu/example_build/qemu_virt/build_libthreadx.sh + +This script builds the library and the demo application kernel.elf. + + +2. Demonstration System (QEMU) + +The provided example is targeted at QEMU's virt platform. After building the +example, the produced kernel.elf can be executed in QEMU: + + qemu-system-riscv32 -nographic -smp 1 -bios none -m 128M -machine virt -kernel kernel.elf + +Typical QEMU features used: +- Single-core CPU +- UART serial console +- PLIC (Platform-Level Interrupt Controller) +- CLINT (Core-Local Interruptor) for timer + + +3. System Initialization + +Entry Point + +The example startup code begins at the _start label in entry.s. This startup +code performs hardware initialization including: +- Check hart ID (only hart 0 continues; others enter WFI loop) +- Zero general-purpose registers +- Set up initial stack pointer +- Clear BSS section +- Jump to main() + +Low-Level Port Initialization (tx_initialize_low_level.S) + +The _tx_initialize_low_level function: +- Saves the system stack pointer to _tx_thread_system_stack_ptr +- Records first free RAM address from __tx_free_memory_start symbol +- Initializes floating-point control/status register (FCSR) if floating point enabled + +Board Initialization (board.c) + +After tx_initialize_low_level returns, main() calls board_init() to: +- Initialize PLIC (Platform-Level Interrupt Controller) +- Initialize UART +- Initialize hardware timer (CLINT) +- Set trap vector (mtvec) to point to trap handler + + +4. Register Usage and Stack Frames + +The RISC-V32 ABI defines t0-t6 and a0-a7 as caller-saved (scratch) registers. +All other registers used by a function must be preserved by the function. + +ThreadX takes advantage of this: when a context switch happens during a +function call, only the non-scratch registers need to be saved. + +Stack Frame Types + +Two types of stack frames exist: + +A. Interrupt Frame (stack type = 1) + Created when an interrupt occurs during thread execution. + Saves all registers including caller-saved registers. + Size: 65*4 = 260 bytes (with FP), or 32*4 = 128 bytes (without FP) + +B. Solicited Frame (stack type = 0) + Created when a thread voluntarily yields via ThreadX service calls. + Saves only callee-saved registers (s0-s11) and mstatus. + Size: 29*4 = 116 bytes (with FP), or 16*4 = 64 bytes (without FP) + + +Stack Layout for Interrupt Frame (with FP enabled): + + Index Offset Register Description + ───────────────────────────────────────────────── + 0 0x00 -- Stack type (1 = interrupt) + 1 0x04 s11 Preserved register + 2 0x08 s10 Preserved register + 3 0x0C s9 Preserved register + 4 0x10 s8 Preserved register + 5 0x14 s7 Preserved register + 6 0x18 s6 Preserved register + 7 0x1C s5 Preserved register + 8 0x20 s4 Preserved register + 9 0x24 s3 Preserved register + 10 0x28 s2 Preserved register + 11 0x2C s1 Preserved register + 12 0x30 s0 Preserved register + 13 0x34 t6 Scratch register + 14 0x38 t5 Scratch register + 15 0x3C t4 Scratch register + 16 0x40 t3 Scratch register + 17 0x44 t2 Scratch register + 18 0x48 t1 Scratch register + 19 0x4C t0 Scratch register + 20 0x50 a7 Argument register + 21 0x54 a6 Argument register + 22 0x58 a5 Argument register + 23 0x5C a4 Argument register + 24 0x60 a3 Argument register + 25 0x64 a2 Argument register + 26 0x68 a1 Argument register + 27 0x6C a0 Argument register + 28 0x70 ra Return address + 29 0x74 -- Reserved + 30 0x78 mepc Machine exception PC + 31-46 0x7C-0xB8 fs0-fs7 Preserved FP registers* + 47-62 0xBC-0xF8 ft0-ft11 Scratch FP registers* + 63 0xFC fcsr FP control/status register + ───────────────────────────────────────────────── + *Note: In ilp32d ABI, FP registers are 8 bytes each, but current + port implementation uses 4-byte indexing which may cause + overlap if fsd/fld are used. + + +5. Interrupt Handling + +Machine Mode Operation + +ThreadX operates in machine mode (M-mode), the highest privilege level. +All interrupts and exceptions trap to machine mode. + +Interrupt Sources + +1. Machine Timer Interrupt (MTI): + - Triggered by CLINT when mtime >= mtimecmp + - Handled by _tx_timer_interrupt (src/tx_timer_interrupt.S) + - Called from trap handler in trap.c + +2. External Interrupts (MEI): + - Routed through PLIC + - Handler in trap.c calls registered ISR callbacks + +3. Software Interrupts (MSI): + - Supported but not actively used in this port + +Interrupt Flow + +1. Hardware trap entry (automatic): + - mepc <- PC (address of interrupted instruction) + - mcause <- exception/interrupt code + - mstatus.MPIE <- mstatus.MIE (save interrupt-enable state) + - mstatus.MIE <- 0 (disable interrupts) + - mstatus.MPP <- Machine mode + - PC <- mtvec (points to trap_entry in entry.s) + +2. Trap entry (entry.s): + - Allocates interrupt stack frame (32*4 or 65*4 bytes depending on FP) + - Saves RA (x1) on stack + - Calls _tx_thread_context_save + +3. Context save (_tx_thread_context_save.S): + - Increments _tx_thread_system_state (nested interrupt counter) + - If nested interrupt: saves remaining registers and returns to ISR + - If first interrupt: saves full context, switches to system stack + +4. Trap handler (trap.c): + - Examines mcause to determine interrupt type + - Dispatches to appropriate handler (_tx_timer_interrupt or PLIC handler) + - Returns to context restore + +5. Context restore (_tx_thread_context_restore.S): + - Decrements _tx_thread_system_state + - Checks if preemption needed + - Restores thread context or switches to next ready thread via scheduler + - Returns to interrupted thread or executes new thread + + +Interrupt Control Macros + +TX_DISABLE and TX_RESTORE macros atomically manage the MIE bit in mstatus: + + TX_DISABLE: Saves and clears MIE bit via csrrci (CSR read-clear immediate) + TX_RESTORE: Restores only MIE bit via csrrs (CSR read-set) + Other mstatus bits remain unchanged + +These are defined in ports/risc-v32/gnu/inc/tx_port.h and use the +_tx_thread_interrupt_control() function. + + +6. Thread Scheduling and Context Switching + +Thread Scheduler (src/tx_thread_schedule.S) + +The scheduler: +1. Enables interrupts while waiting for next thread +2. Spins until _tx_thread_execute_ptr becomes non-NULL +3. Disables interrupts (critical section) +4. Sets _tx_thread_current_ptr = _tx_thread_execute_ptr +5. Increments thread's run count +6. Switches to thread's stack +7. Determines stack frame type and restores context: + - Interrupt frame: full context restored, returns via mret + - Solicited frame: minimal context restored, returns via ret + +Initial Thread Stack Frame (src/tx_thread_stack_build.S) + +New threads start with a fake interrupt frame containing: +- All registers initialized to 0 +- ra (x1) = 0 +- mepc = entry function pointer +- Stack type = 1 (interrupt frame) +- Floating-point registers initialized based on ABI + + +7. Port Configuration and Macros + +Default Configurations (in ports/risc-v32/gnu/inc/tx_port.h): + + TX_MINIMUM_STACK 1024 /* Minimum thread stack size */ + TX_TIMER_THREAD_STACK_SIZE 1024 /* Timer thread stack size */ + TX_TIMER_THREAD_PRIORITY 0 /* Timer thread priority */ + TX_MAX_PRIORITIES 32 /* Must be multiple of 32 */ + +These can be overridden in tx_user.h or on the compiler command line. + + +8. Build Configuration + +CMake Toolchain File: cmake/riscv32_gnu.cmake + +Compiler Flags: + -march=rv32gc RV32 with IMAFD+C extensions + -mabi=ilp32d 32-bit integers/pointers, double-precision FP in registers + -mcmodel=medany ±2GB addressability + -D__ASSEMBLER__ For assembly files + +ABI Selection + +The port uses ilp32d ABI which includes: +- 32-bit integers and pointers +- Double-precision floating-point arguments in registers +- Floating-point registers f0-f31 + +When building with floating-point ABI: +- FP registers and FCSR are saved/restored in context switches +- Stack frames expand from 32*REGBYTES to 65*REGBYTES +- Conditional compilation uses __riscv_float_abi_double / __riscv_float_abi_single + + +9. File Organization + +Port-specific files (ports/risc-v32/gnu/): + +Core assembly files (src/): + - tx_initialize_low_level.S Initial setup and system state + - tx_thread_context_save.S Save context on interrupt entry + - tx_thread_context_restore.S Restore context on interrupt exit + - tx_thread_schedule.S Thread scheduler + - tx_thread_system_return.S Solicited context save for voluntary yield + - tx_thread_stack_build.S Build initial stack frame for new thread + - tx_thread_interrupt_control.S Interrupt enable/disable control + - tx_timer_interrupt.S Timer interrupt handler + +Header file (inc/): + - tx_port.h Port-specific defines and macros + +Example files (example_build/qemu_virt/): + - entry.s Startup code, trap entry point + - board.c, uart.c, hwtimer.c Platform-specific initialization + - plic.c PLIC interrupt controller driver + - trap.c Trap/exception dispatcher + - link.lds Linker script for QEMU virt + - build_libthreadx.sh Build script + + +10. Linker Script Requirements + +The linker script must provide: + +1. Entry point: + ENTRY(_start) + +2. Memory layout: + - .text section (code) + - .rodata section (read-only data) + - .data section (initialized data) + - .bss section (uninitialized data) + +3. Symbols: + - _end: First free memory address (used by ThreadX allocation) + - _bss_start, _bss_end: For zero initialization + - Initial stack space (example: 4KB) + +4. Alignment: + - 16-byte alignment throughout (RISC-V requirement) + +Example from QEMU virt build: + + SECTIONS + { + . = 0x80000000; /* QEMU virt base address */ + + .text : { *(.text .text.*) } + .rodata : { *(.rodata .rodata.*) } + .data : { *(.data .data.*) } + .bss : { *(.bss .bss.*) } + + .stack : { + . = ALIGN(4096); + _sysstack_start = .; + . += 0x1000; /* 4KB initial stack */ + _sysstack_end = .; + } + + PROVIDE(_end = .); + } + + +11. Floating-Point Support + +When building with ilp32d ABI and FP enabled: + +- FP registers f0-f31 and FCSR are saved/restored during context switches +- Stack frames increase from 32*REGBYTES to 65*REGBYTES (128 to 260 bytes) +- MSTATUS.FS (floating-point state) field is set to indicate dirty FP state + +Stack frame differences: +- Without FP: 32*4 = 128 bytes (interrupt), 16*4 = 64 bytes (solicited) +- With FP: 65*4 = 260 bytes (interrupt), 29*4 = 116 bytes (solicited) + + +12. Performance and Debugging + +Performance Optimization + +Build optimizations: +- Use -O2 or -O3 for production (example uses -O0 for debugging) +- Enable -Wl,--gc-sections to remove unused code +- Define TX_DISABLE_ERROR_CHECKING to remove parameter checks +- Consider -flto for link-time optimization + +Debugging with QEMU and GDB + +Start QEMU in debug mode: + qemu-system-riscv32 -nographic -smp 1 -bios none -m 128M \ + -machine virt -kernel kernel.elf -s -S + + -s: Enable GDB server on TCP port 1234 + -S: Pause at startup waiting for GDB + +Connect GDB: + riscv32-unknown-elf-gdb kernel.elf + (gdb) target remote :1234 + (gdb) break main + (gdb) continue + +Useful GDB commands: + (gdb) info registers # View general registers + (gdb) info all-registers # Include CSR and FP registers + (gdb) p/x $mstatus # View machine status register + (gdb) x/32xw $sp # Examine stack memory + (gdb) p *_tx_thread_current_ptr # View current thread control block + + +13. Platform-Specific Notes (QEMU virt) + +PLIC Configuration + +The PLIC (Platform-Level Interrupt Controller) is memory-mapped at 0x0C000000: + +- Enables up to 1024 interrupt sources +- Supports priority levels 0-7 (0 = disabled) +- Requires per-hart priority threshold and enable register configuration + +Example PLIC usage (from plic.c): + plic_irq_enable(irq_number); # Enable specific interrupt + plic_prio_set(irq_number, priority);# Set priority level + +CLINT Configuration + +The CLINT (Core-Local Interruptor) is memory-mapped at 0x02000000: + +- CLINT_MSIP(hartid): 0x0000 + 4*hartid (software interrupt) +- CLINT_MTIMECMP(hartid): 0x4000 + 8*hartid (timer compare) +- CLINT_MTIME: 0xBFF8 (timer value, read-only) + +Timer frequency is platform-dependent (example uses 10MHz). + +Multi-Core Considerations + +The current port is single-core focused: +- Only hart 0 continues from reset; others enter WFI loop +- _tx_thread_system_state is a global variable +- No per-hart data structures + + +14. Revision History + +For generic code revision information, refer to readme_threadx_generic.txt. + +The following details the revision history for this RISC-V32 GNU port: + +01-26-2026 Akif Ejaz Brief rewrite with accurate + technical details matching implementation, + register naming per RISC-V ABI, and + complete interrupt flow documentation + (Adapted from RISC-V64 port) + + +Copyright (c) 1996-2026 Microsoft Corporation + +https://azure.com/rtos diff --git a/ports/risc-v32/gnu/src/tx_initialize_low_level.S b/ports/risc-v32/gnu/src/tx_initialize_low_level.S new file mode 100644 index 000000000..70fefc848 --- /dev/null +++ b/ports/risc-v32/gnu/src/tx_initialize_low_level.S @@ -0,0 +1,118 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Initialize */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .section .data + .global __tx_free_memory_start +__tx_free_memory_start: + + + .section .text +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level RISC-V32/GNU */ +/* 6.4.x */ +/* AUTHOR */ +/* */ +/* Akif Ejaz, 10xEngineers */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for any low-level processor */ +/* initialization, including setting up interrupt vectors, setting */ +/* up a periodic timer interrupt source, saving the system stack */ +/* pointer for use in ISR processing later, and finding the first */ +/* available RAM memory address for tx_application_define. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 23-12-2025 Akif Ejaz Initial Version 6.4.x */ +/* */ +/**************************************************************************/ +/* VOID _tx_initialize_low_level(VOID) +{ */ + .global _tx_initialize_low_level + .weak _tx_initialize_low_level +_tx_initialize_low_level: + + /* Save the system stack pointer. */ + /* _tx_thread_system_stack_ptr = sp; */ + + la t0, _tx_thread_system_stack_ptr // Pickup address of system stack ptr + sw sp, 0(t0) // Save system stack pointer + + /* Pickup first free address. */ + /* _tx_initialize_unused_memory(__tx_free_memory_start); */ + + la t0, __tx_free_memory_start // Pickup first free address + la t1, _tx_initialize_unused_memory // Pickup address of unused memory + sw t0, 0(t1) // Save unused memory address + + /* Initialize floating point control/status register if floating point is enabled. */ +#ifdef __riscv_flen + li t0, 0 + csrw fcsr, t0 // Clear FP control/status register +#endif + + ret + +/* Timer Interrupt Handler Note: + Platform-specific implementations must provide their own timer ISR. + The timer interrupt handler should follow this execution flow: + + 1. Disable interrupts (if not done by hardware exception entry) + 2. Allocate interrupt stack frame (65*4 bytes with FP, 32*4 bytes without) + 3. Save RA (x1) on the stack at offset 28*4 + 4. Call _tx_thread_context_save to save thread context + 5. Call _tx_timer_interrupt to process the timer tick + 6. Call _tx_thread_context_restore to resume execution (does not return) + + Example (for CLINT timer): + + _tx_timer_interrupt_handler: + addi sp, sp, -32*4 + sw ra, 28*4(sp) + call _tx_thread_context_save + call _tx_timer_interrupt + j _tx_thread_context_restore + + The port assumes Machine mode (M-mode) execution. + For Supervisor mode (S-mode), use sstatus and SIE/SPIE instead of mstatus. + See the RISC-V Privileged Specification for more details. */ \ No newline at end of file diff --git a/ports/risc-v32/gnu/src/tx_thread_context_restore.S b/ports/risc-v32/gnu/src/tx_thread_context_restore.S new file mode 100644 index 000000000..ba553a469 --- /dev/null +++ b/ports/risc-v32/gnu/src/tx_thread_context_restore.S @@ -0,0 +1,416 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .section .text +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_restore RISC-V32/GNU */ +/* 6.4.x */ +/* AUTHOR */ +/* */ +/* Akif Ejaz, 10xEngineers */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function restores the interrupt context if it is processing a */ +/* nested interrupt. If not, it returns to the interrupt thread if no */ +/* preemption is necessary. Otherwise, if preemption is necessary or */ +/* if no thread was running, the function returns to the scheduler. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_schedule Thread scheduling routine */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs Interrupt Service Routines */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 23-12-2025 Akif Ejaz Initial Version 6.4.x */ +/* */ +/**************************************************************************/ +/* VOID _tx_thread_context_restore(VOID) +{ */ + .global _tx_thread_context_restore +_tx_thread_context_restore: + + /* Lockout interrupts. */ + + csrci mstatus, 0x08 // Disable interrupts (MIE bit 3) + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + call _tx_execution_isr_exit // Call the ISR execution exit function +#endif + + /* Determine if interrupts are nested. */ + /* if (--_tx_thread_system_state) + { */ + + la t0, _tx_thread_system_state // Pickup addr of nested interrupt count + lw t1, 0(t0) // Pickup nested interrupt count + addi t1, t1, -1 // Decrement the nested interrupt counter + sw t1, 0(t0) // Store new nested count + beqz t1, _tx_thread_not_nested_restore // If 0, not nested restore + + /* Interrupts are nested. */ + + /* Just recover the saved registers and return to the point of + interrupt. */ + + /* Recover floating point registers. */ +#if defined(__riscv_float_abi_single) + flw f0, 31*4(sp) // Recover ft0 + flw f1, 32*4(sp) // Recover ft1 + flw f2, 33*4(sp) // Recover ft2 + flw f3, 34*4(sp) // Recover ft3 + flw f4, 35*4(sp) // Recover ft4 + flw f5, 36*4(sp) // Recover ft5 + flw f6, 37*4(sp) // Recover ft6 + flw f7, 38*4(sp) // Recover ft7 + flw f10, 41*4(sp) // Recover fa0 + flw f11, 42*4(sp) // Recover fa1 + flw f12, 43*4(sp) // Recover fa2 + flw f13, 44*4(sp) // Recover fa3 + flw f14, 45*4(sp) // Recover fa4 + flw f15, 46*4(sp) // Recover fa5 + flw f16, 47*4(sp) // Recover fa6 + flw f17, 48*4(sp) // Recover fa7 + flw f28, 59*4(sp) // Recover ft8 + flw f29, 60*4(sp) // Recover ft9 + flw f30, 61*4(sp) // Recover ft10 + flw f31, 62*4(sp) // Recover ft11 + lw t0, 63*4(sp) // Recover fcsr + csrw fcsr, t0 // Restore fcsr +#elif defined(__riscv_float_abi_double) + fld f0, 31*4(sp) // Recover ft0 + fld f1, 32*4(sp) // Recover ft1 + fld f2, 33*4(sp) // Recover ft2 + fld f3, 34*4(sp) // Recover ft3 + fld f4, 35*4(sp) // Recover ft4 + fld f5, 36*4(sp) // Recover ft5 + fld f6, 37*4(sp) // Recover ft6 + fld f7, 38*4(sp) // Recover ft7 + fld f10, 41*4(sp) // Recover fa0 + fld f11, 42*4(sp) // Recover fa1 + fld f12, 43*4(sp) // Recover fa2 + fld f13, 44*4(sp) // Recover fa3 + fld f14, 45*4(sp) // Recover fa4 + fld f15, 46*4(sp) // Recover fa5 + fld f16, 47*4(sp) // Recover fa6 + fld f17, 48*4(sp) // Recover fa7 + fld f28, 59*4(sp) // Recover ft8 + fld f29, 60*4(sp) // Recover ft9 + fld f30, 61*4(sp) // Recover ft10 + fld f31, 62*4(sp) // Recover ft11 + lw t0, 63*4(sp) // Recover fcsr + csrw fcsr, t0 // Restore fcsr +#endif + + /* Recover standard registers. */ + + /* Restore registers, + Skip global pointer because that does not change. + Also skip the saved registers since they have been restored by any function we called, + except s0 since we use it ourselves. */ + + lw t0, 30*4(sp) // Recover mepc + csrw mepc, t0 // Setup mepc + + /* Compose mstatus via read/modify/write to avoid clobbering unrelated bits. + Set MPIE and restore MPP to Machine, preserve other fields. */ + + csrr t1, mstatus + + /* Clear MPP/MPIE/MIE bits in t1 then set desired values. */ + + li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08) + li t3, 0x1800 // Set MPP to Machine mode (bits 12:11) + + /* Construct new mstatus in t1: clear mask bits, set MPP/MPIE and optionally FP bit, + preserve everything except the bits we will modify. */ + + li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE + and t1, t1, t4 + or t1, t1, t3 + +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + li t0, 0x2000 // Set FS bits (bits 14:13 to 01) for FP state + or t1, t1, t0 +#endif + csrw mstatus, t1 // Update mstatus safely + + lw ra, 28*4(sp) // Recover return address + lw t0, 19*4(sp) // Recover t0 + lw t1, 18*4(sp) // Recover t1 + lw t2, 17*4(sp) // Recover t2 + lw s0, 12*4(sp) // Recover s0 + lw a0, 27*4(sp) // Recover a0 + lw a1, 26*4(sp) // Recover a1 + lw a2, 25*4(sp) // Recover a2 + lw a3, 24*4(sp) // Recover a3 + lw a4, 23*4(sp) // Recover a4 + lw a5, 22*4(sp) // Recover a5 + lw a6, 21*4(sp) // Recover a6 + lw a7, 20*4(sp) // Recover a7 + lw t3, 16*4(sp) // Recover t3 + lw t4, 15*4(sp) // Recover t4 + lw t5, 14*4(sp) // Recover t5 + lw t6, 13*4(sp) // Recover t6 + +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi sp, sp, 65*4 // Recover stack frame - with floating point enabled +#else + addi sp, sp, 32*4 // Recover stack frame - without floating point enabled +#endif + mret // Return to point of interrupt + + /* } */ +_tx_thread_not_nested_restore: + /* Determine if a thread was interrupted and no preemption is required. */ + /* else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr) + || (_tx_thread_preempt_disable)) + { */ + + la t0, _tx_thread_current_ptr // Pickup current thread pointer address + lw t1, 0(t0) // Pickup current thread pointer + + beqz t1, _tx_thread_idle_system_restore // If NULL, idle system restore + + + la t0, _tx_thread_preempt_disable // Pickup preempt disable flag address + lw t2, 0(t0) // Pickup preempt disable flag (UINT) + + bgtz t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread + + + la t0, _tx_thread_execute_ptr // Pickup thread execute pointer address + lw t2, 0(t0) // Pickup thread execute pointer + + bne t1, t2, _tx_thread_preempt_restore // If higher-priority thread is ready, preempt + + +_tx_thread_no_preempt_restore: + /* Restore interrupted thread or ISR. */ + + /* Pickup the saved stack pointer. */ + /* sp = _tx_thread_current_ptr -> tx_thread_stack_ptr; */ + + lw sp, 8(t1) // Switch back to thread's stack + + /* Recover floating point registers. */ +#if defined(__riscv_float_abi_single) + flw f0, 31*4(sp) // Recover ft0 + flw f1, 32*4(sp) // Recover ft1 + flw f2, 33*4(sp) // Recover ft2 + flw f3, 34*4(sp) // Recover ft3 + flw f4, 35*4(sp) // Recover ft4 + flw f5, 36*4(sp) // Recover ft5 + flw f6, 37*4(sp) // Recover ft6 + flw f7, 38*4(sp) // Recover ft7 + flw f10, 41*4(sp) // Recover fa0 + flw f11, 42*4(sp) // Recover fa1 + flw f12, 43*4(sp) // Recover fa2 + flw f13, 44*4(sp) // Recover fa3 + flw f14, 45*4(sp) // Recover fa4 + flw f15, 46*4(sp) // Recover fa5 + flw f16, 47*4(sp) // Recover fa6 + flw f17, 48*4(sp) // Recover fa7 + flw f28, 59*4(sp) // Recover ft8 + flw f29, 60*4(sp) // Recover ft9 + flw f30, 61*4(sp) // Recover ft10 + flw f31, 62*4(sp) // Recover ft11 + lw t0, 63*4(sp) // Recover fcsr + csrw fcsr, t0 // Restore fcsr +#elif defined(__riscv_float_abi_double) + fld f0, 31*4(sp) // Recover ft0 + fld f1, 32*4(sp) // Recover ft1 + fld f2, 33*4(sp) // Recover ft2 + fld f3, 34*4(sp) // Recover ft3 + fld f4, 35*4(sp) // Recover ft4 + fld f5, 36*4(sp) // Recover ft5 + fld f6, 37*4(sp) // Recover ft6 + fld f7, 38*4(sp) // Recover ft7 + fld f10, 41*4(sp) // Recover fa0 + fld f11, 42*4(sp) // Recover fa1 + fld f12, 43*4(sp) // Recover fa2 + fld f13, 44*4(sp) // Recover fa3 + fld f14, 45*4(sp) // Recover fa4 + fld f15, 46*4(sp) // Recover fa5 + fld f16, 47*4(sp) // Recover fa6 + fld f17, 48*4(sp) // Recover fa7 + fld f28, 59*4(sp) // Recover ft8 + fld f29, 60*4(sp) // Recover ft9 + fld f30, 61*4(sp) // Recover ft10 + fld f31, 62*4(sp) // Recover ft11 + lw t0, 63*4(sp) // Recover fcsr + csrw fcsr, t0 // Restore fcsr +#endif + + /* Recover the saved context and return to the point of interrupt. */ + + /* Recover standard registers. */ + /* Restore registers, + Skip global pointer because that does not change */ + + lw t0, 30*4(sp) // Recover mepc + csrw mepc, t0 // Setup mepc + + /* Compose mstatus via read/modify/write to avoid clobbering unrelated bits. */ + + csrr t1, mstatus + li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08) + li t3, 0x1800 // Set MPP to Machine mode + li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE + and t1, t1, t4 + or t1, t1, t3 + +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + li t0, 0x2000 // Set FS bits for FP state + or t1, t1, t0 +#endif + csrw mstatus, t1 // Update mstatus safely + + lw ra, 28*4(sp) // Recover return address + lw t0, 19*4(sp) // Recover t0 + lw t1, 18*4(sp) // Recover t1 + lw t2, 17*4(sp) // Recover t2 + lw s0, 12*4(sp) // Recover s0 + lw a0, 27*4(sp) // Recover a0 + lw a1, 26*4(sp) // Recover a1 + lw a2, 25*4(sp) // Recover a2 + lw a3, 24*4(sp) // Recover a3 + lw a4, 23*4(sp) // Recover a4 + lw a5, 22*4(sp) // Recover a5 + lw a6, 21*4(sp) // Recover a6 + lw a7, 20*4(sp) // Recover a7 + lw t3, 16*4(sp) // Recover t3 + lw t4, 15*4(sp) // Recover t4 + lw t5, 14*4(sp) // Recover t5 + lw t6, 13*4(sp) // Recover t6 + +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi sp, sp, 65*4 // Recover stack frame - with floating point enabled +#else + addi sp, sp, 32*4 // Recover stack frame - without floating point enabled +#endif + mret // Return to point of interrupt + + /* } + else + { */ +_tx_thread_preempt_restore: + /* Instead of directly activating the thread again, ensure we save the + entire stack frame by saving the remaining registers. */ + + lw t0, 8(t1) // Pickup thread's stack pointer + ori t3, zero, 1 // Build interrupt stack type + sw t3, 0(t0) // Store stack type + + /* Store floating point preserved registers. */ +#ifdef __riscv_float_abi_single + fsw f8, 39*4(t0) // Store fs0 + fsw f9, 40*4(t0) // Store fs1 + fsw f18, 49*4(t0) // Store fs2 + fsw f19, 50*4(t0) // Store fs3 + fsw f20, 51*4(t0) // Store fs4 + fsw f21, 52*4(t0) // Store fs5 + fsw f22, 53*4(t0) // Store fs6 + fsw f23, 54*4(t0) // Store fs7 + fsw f24, 55*4(t0) // Store fs8 + fsw f25, 56*4(t0) // Store fs9 + fsw f26, 57*4(t0) // Store fs10 + fsw f27, 58*4(t0) // Store fs11 +#elif defined(__riscv_float_abi_double) + fsd f8, 39*4(t0) // Store fs0 + fsd f9, 40*4(t0) // Store fs1 + fsd f18, 49*4(t0) // Store fs2 + fsd f19, 50*4(t0) // Store fs3 + fsd f20, 51*4(t0) // Store fs4 + fsd f21, 52*4(t0) // Store fs5 + fsd f22, 53*4(t0) // Store fs6 + fsd f23, 54*4(t0) // Store fs7 + fsd f24, 55*4(t0) // Store fs8 + fsd f25, 56*4(t0) // Store fs9 + fsd f26, 57*4(t0) // Store fs10 + fsd f27, 58*4(t0) // Store fs11 +#endif + + /* Store standard preserved registers. */ + + sw x9, 11*4(t0) // Store s1 + sw x18, 10*4(t0) // Store s2 + sw x19, 9*4(t0) // Store s3 + sw x20, 8*4(t0) // Store s4 + sw x21, 7*4(t0) // Store s5 + sw x22, 6*4(t0) // Store s6 + sw x23, 5*4(t0) // Store s7 + sw x24, 4*4(t0) // Store s8 + sw x25, 3*4(t0) // Store s9 + sw x26, 2*4(t0) // Store s10 + sw x27, 1*4(t0) // Store s11 + // Note: s0 is already stored! + + /* Save the remaining time-slice and disable it. */ + /* if (_tx_timer_time_slice) + { */ + + la t0, _tx_timer_time_slice // Pickup time slice variable address + lw t2, 0(t0) // Pickup time slice + beqz t2, _tx_thread_dont_save_ts // If 0, skip time slice processing + + /* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice + _tx_timer_time_slice = 0; */ + + sw t2, 24(t1) // Save current time slice + sw x0, 0(t0) // Clear global time slice + + + /* } */ +_tx_thread_dont_save_ts: + /* Clear the current task pointer. */ + /* _tx_thread_current_ptr = TX_NULL; */ + + /* Return to the scheduler. */ + /* _tx_thread_schedule(); */ + + la t0, _tx_thread_current_ptr // Pickup current thread pointer address + sw x0, 0(t0) // Clear current thread pointer + + /* } */ + +_tx_thread_idle_system_restore: + /* Just return back to the scheduler! */ + j _tx_thread_schedule // Return to scheduler + +/* } */ diff --git a/ports/risc-v32/gnu/src/tx_thread_context_save.S b/ports/risc-v32/gnu/src/tx_thread_context_save.S new file mode 100644 index 000000000..3b7496b3d --- /dev/null +++ b/ports/risc-v32/gnu/src/tx_thread_context_save.S @@ -0,0 +1,277 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .section .text +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_save RISC-V32/GNU */ +/* 6.4.x */ +/* AUTHOR */ +/* */ +/* Akif Ejaz, 10xEngineers */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function saves the context of an executing thread in the */ +/* beginning of interrupt processing. The function also ensures that */ +/* the system stack is used upon return to the calling ISR. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 23-12-2025 Akif Ejaz Initial Version 6.4.x */ +/* */ +/**************************************************************************/ +/* VOID _tx_thread_context_save(VOID) +{ */ + .global _tx_thread_context_save +_tx_thread_context_save: + + /* Upon entry to this routine, RA/x1 has been saved on the stack + and the stack has been already allocated for the entire context: + addi sp, sp, -32*4 (or -65*4) + sw ra, 28*4(sp) + */ + + sw t0, 19*4(sp) // Store t0 + sw t1, 18*4(sp) // Store t1 + + /* Check for a nested interrupt. */ + /* if (_tx_thread_system_state++) + { */ + + la t0, _tx_thread_system_state // Pickup addr of system state var + lw t1, 0(t0) // Pickup system state + addi t1, t1, 1 // Increment system state + sw t1, 0(t0) // Store system state + li t0, 1 + bgt t1, t0, _tx_thread_nested_save // If it's more than 1, nested interrupt + + /* First level interrupt, save the rest of the scratch registers and + check for a thread to preempt. */ + + sw t2, 17*4(sp) // Store t2 + sw s0, 12*4(sp) // Store s0 + sw a0, 27*4(sp) // Store a0 + sw a1, 26*4(sp) // Store a1 + sw a2, 25*4(sp) // Store a2 + sw a3, 24*4(sp) // Store a3 + sw a4, 23*4(sp) // Store a4 + sw a5, 22*4(sp) // Store a5 + sw a6, 21*4(sp) // Store a6 + sw a7, 20*4(sp) // Store a7 + sw t3, 16*4(sp) // Store t3 + sw t4, 15*4(sp) // Store t4 + sw t5, 14*4(sp) // Store t5 + sw t6, 13*4(sp) // Store t6 + + /* Save floating point registers. */ +#if defined(__riscv_float_abi_single) + fsw f0, 31*4(sp) // Store ft0 + fsw f1, 32*4(sp) // Store ft1 + fsw f2, 33*4(sp) // Store ft2 + fsw f3, 34*4(sp) // Store ft3 + fsw f4, 35*4(sp) // Store ft4 + fsw f5, 36*4(sp) // Store ft5 + fsw f6, 37*4(sp) // Store ft6 + fsw f7, 38*4(sp) // Store ft7 + fsw f10, 41*4(sp) // Store fa0 + fsw f11, 42*4(sp) // Store fa1 + fsw f12, 43*4(sp) // Store fa2 + fsw f13, 44*4(sp) // Store fa3 + fsw f14, 45*4(sp) // Store fa4 + fsw f15, 46*4(sp) // Store fa5 + fsw f16, 47*4(sp) // Store fa6 + fsw f17, 48*4(sp) // Store fa7 + fsw f28, 59*4(sp) // Store ft8 + fsw f29, 60*4(sp) // Store ft9 + fsw f30, 61*4(sp) // Store ft10 + fsw f31, 62*4(sp) // Store ft11 + csrr t0, fcsr + sw t0, 63*4(sp) // Store fcsr +#elif defined(__riscv_float_abi_double) + fsd f0, 31*4(sp) // Store ft0 + fsd f1, 32*4(sp) // Store ft1 + fsd f2, 33*4(sp) // Store ft2 + fsd f3, 34*4(sp) // Store ft3 + fsd f4, 35*4(sp) // Store ft4 + fsd f5, 36*4(sp) // Store ft5 + fsd f6, 37*4(sp) // Store ft6 + fsd f7, 38*4(sp) // Store ft7 + fsd f10, 41*4(sp) // Store fa0 + fsd f11, 42*4(sp) // Store fa1 + fsd f12, 43*4(sp) // Store fa2 + fsd f13, 44*4(sp) // Store fa3 + fsd f14, 45*4(sp) // Store fa4 + fsd f15, 46*4(sp) // Store fa5 + fsd f16, 47*4(sp) // Store fa6 + fsd f17, 48*4(sp) // Store fa7 + fsd f28, 59*4(sp) // Store ft8 + fsd f29, 60*4(sp) // Store ft9 + fsd f30, 61*4(sp) // Store ft10 + fsd f31, 62*4(sp) // Store ft11 + csrr t0, fcsr + sw t0, 63*4(sp) // Store fcsr +#endif + + csrr t0, mepc + sw t0, 30*4(sp) // Save it on the stack + + /* Save mstatus. */ + csrr t0, mstatus + sw t0, 29*4(sp) + + la t1, _tx_thread_current_ptr // Pickup address of current thread ptr + lw t2, 0(t1) // Pickup current thread pointer + beqz t2, _tx_thread_idle_system_save // If NULL, idle system was interrupted + + /* Save the current thread's stack pointer and switch to the system stack. */ + /* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; + sp = _tx_thread_system_stack_ptr; */ + + sw sp, 8(t2) // Save stack pointer + la t0, _tx_thread_system_stack_ptr + lw sp, 0(t0) // Switch to system stack + + /* Call the ISR execution exit function if enabled. */ +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + call _tx_execution_isr_enter // Call the ISR execution enter function +#endif + + ret // Return to ISR + +_tx_thread_nested_save: + + /* Nested interrupt! Just save the scratch registers and return to the ISR. */ + + sw t2, 17*4(sp) // Store t2 + sw s0, 12*4(sp) // Store s0 + sw a0, 27*4(sp) // Store a0 + sw a1, 26*4(sp) // Store a1 + sw a2, 25*4(sp) // Store a2 + sw a3, 24*4(sp) // Store a3 + sw a4, 23*4(sp) // Store a4 + sw a5, 22*4(sp) // Store a5 + sw a6, 21*4(sp) // Store a6 + sw a7, 20*4(sp) // Store a7 + sw t3, 16*4(sp) // Store t3 + sw t4, 15*4(sp) // Store t4 + sw t5, 14*4(sp) // Store t5 + sw t6, 13*4(sp) // Store t6 + + /* Save floating point registers. */ +#if defined(__riscv_float_abi_single) + fsw f0, 31*4(sp) // Store ft0 + fsw f1, 32*4(sp) // Store ft1 + fsw f2, 33*4(sp) // Store ft2 + fsw f3, 34*4(sp) // Store ft3 + fsw f4, 35*4(sp) // Store ft4 + fsw f5, 36*4(sp) // Store ft5 + fsw f6, 37*4(sp) // Store ft6 + fsw f7, 38*4(sp) // Store ft7 + fsw f10, 41*4(sp) // Store fa0 + fsw f11, 42*4(sp) // Store fa1 + fsw f12, 43*4(sp) // Store fa2 + fsw f13, 44*4(sp) // Store fa3 + fsw f14, 45*4(sp) // Store fa4 + fsw f15, 46*4(sp) // Store fa5 + fsw f16, 47*4(sp) // Store fa6 + fsw f17, 48*4(sp) // Store fa7 + fsw f28, 59*4(sp) // Store ft8 + fsw f29, 60*4(sp) // Store ft9 + fsw f30, 61*4(sp) // Store ft10 + fsw f31, 62*4(sp) // Store ft11 + csrr t0, fcsr + sw t0, 63*4(sp) // Store fcsr +#elif defined(__riscv_float_abi_double) + fsd f0, 31*4(sp) // Store ft0 + fsd f1, 32*4(sp) // Store ft1 + fsd f2, 33*4(sp) // Store ft2 + fsd f3, 34*4(sp) // Store ft3 + fsd f4, 35*4(sp) // Store ft4 + fsd f5, 36*4(sp) // Store ft5 + fsd f6, 37*4(sp) // Store ft6 + fsd f7, 38*4(sp) // Store ft7 + fsd f10, 41*4(sp) // Store fa0 + fsd f11, 42*4(sp) // Store fa1 + fsd f12, 43*4(sp) // Store fa2 + fsd f13, 44*4(sp) // Store fa3 + fsd f14, 45*4(sp) // Store fa4 + fsd f15, 46*4(sp) // Store fa5 + fsd f16, 47*4(sp) // Store fa6 + fsd f17, 48*4(sp) // Store fa7 + fsd f28, 59*4(sp) // Store ft8 + fsd f29, 60*4(sp) // Store ft9 + fsd f30, 61*4(sp) // Store ft10 + fsd f31, 62*4(sp) // Store ft11 + csrr t0, fcsr + sw t0, 63*4(sp) // Store fcsr +#endif + + csrr t0, mepc + sw t0, 30*4(sp) // Save it on stack + + csrr t0, mstatus + sw t0, 29*4(sp) + + /* Call the ISR execution exit function if enabled. */ +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + call _tx_execution_isr_enter // Call the ISR execution enter function +#endif + + ret // Return to ISR + +_tx_thread_idle_system_save: + + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + call _tx_execution_isr_enter // Call the ISR execution enter function +#endif + + /* Interrupt occurred in the scheduling loop. */ + + /* } +} */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi sp, sp, 65*4 // Recover stack frame - with floating point enabled +#else + addi sp, sp, 32*4 // Recover the reserved stack space +#endif + ret // Return to calling ISR diff --git a/ports/risc-v32/gnu/src/tx_thread_interrupt_control.S b/ports/risc-v32/gnu/src/tx_thread_interrupt_control.S new file mode 100644 index 000000000..8e28cf74f --- /dev/null +++ b/ports/risc-v32/gnu/src/tx_thread_interrupt_control.S @@ -0,0 +1,94 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + + .section .text +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_control RISC-V32/GNU */ +/* 6.4.x */ +/* AUTHOR */ +/* */ +/* Akif Ejaz, 10xEngineers */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for changing the interrupt lockout */ +/* posture of the system. */ +/* */ +/* INPUT */ +/* */ +/* new_posture New interrupt lockout posture */ +/* */ +/* OUTPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 23-12-2025 Akif Ejaz Initial Version 6.4.x */ +/* */ +/**************************************************************************/ +/* UINT _tx_thread_interrupt_control(UINT new_posture) +{ */ + .global _tx_thread_interrupt_control +_tx_thread_interrupt_control: + + /* Pickup current interrupt posture. */ + + csrr a1, mstatus // Pickup mstatus + andi a1, a1, 0x08 // Mask out all but MIE + + /* Check for the new posture. */ + + beqz a0, _tx_thread_interrupt_disable // If 0, disable interrupts + + /* Enable interrupts. */ + + csrsi mstatus, 0x08 // Enable interrupts (MIE bit 3) + j _tx_thread_interrupt_control_exit // Return to caller + +_tx_thread_interrupt_disable: + + /* Disable interrupts. */ + + csrci mstatus, 0x08 // Disable interrupts (MIE bit 3) + +_tx_thread_interrupt_control_exit: + + /* Return the old interrupt posture. */ + + mv a0, a1 // Setup return value + ret // Return to caller + +/* } */ diff --git a/ports/risc-v32/gnu/src/tx_thread_schedule.S b/ports/risc-v32/gnu/src/tx_thread_schedule.S new file mode 100644 index 000000000..edf3462f2 --- /dev/null +++ b/ports/risc-v32/gnu/src/tx_thread_schedule.S @@ -0,0 +1,324 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + + .section .text +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_schedule RISC-V32/GNU */ +/* 6.4.x */ +/* AUTHOR */ +/* */ +/* Akif Ejaz, 10xEngineers */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function waits for a thread control block pointer to appear in */ +/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +/* in the variable, the corresponding thread is resumed. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* _tx_thread_system_return Return to system from thread */ +/* _tx_thread_context_restore Restore thread's context */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 23-12-2025 Akif Ejaz Initial Version 6.4.x */ +/* */ +/**************************************************************************/ +/* VOID _tx_thread_schedule(VOID) +{ */ + .global _tx_thread_schedule +_tx_thread_schedule: + + /* Enable interrupts. */ + + csrsi mstatus, 0x08 // Enable interrupts (MIE bit 3) + + /* Wait for a thread to execute. */ + /* do + { */ +_tx_thread_schedule_loop: + + la t0, _tx_thread_execute_ptr // Pickup address of execute ptr + lw t1, 0(t0) // Pickup execute pointer + bnez t1, _tx_thread_ready_to_run // If non-NULL, a thread is ready to run + +#ifndef TX_NO_WFI + wfi // Wait for interrupt +#endif + j _tx_thread_schedule_loop // Check again + + /* } + while (_tx_thread_execute_ptr == TX_NULL); */ + +_tx_thread_ready_to_run: + + /* At this point, t1 contains the pointer to the thread to execute. + Lockout interrupts. */ + + csrci mstatus, 0x08 // Disable interrupts (MIE bit 3) + + /* Check _tx_thread_execute_ptr again, in case an interrupt occurred + between the check and the disable. */ + + lw t1, 0(t0) // Pickup execute pointer + beqz t1, _tx_thread_schedule_loop // If NULL, go back to wait loop + + /* Yes! We have a thread to execute. */ + /* _tx_thread_current_ptr = _tx_thread_execute_ptr; */ + + la t0, _tx_thread_current_ptr // Pickup address of current thread + sw t1, 0(t0) // Setup current thread pointer + + /* Increment the run count for this thread. */ + /* _tx_thread_current_ptr -> tx_thread_run_count++; */ + + lw t2, 4(t1) // Pickup run count + addi t2, t2, 1 // Increment run count + sw t2, 4(t1) // Store run count + + /* Setup time-slice values. */ + /* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */ + + lw t2, 24(t1) // Pickup thread time-slice + la t3, _tx_timer_time_slice // Pickup address of time-slice + sw t2, 0(t3) // Setup time-slice + + /* Call the thread execution enter function if enabled. */ +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + + call _tx_execution_thread_enter // Call the thread execution enter function +#endif + + /* Switch to the thread's stack. */ + /* sp = _tx_thread_current_ptr -> tx_thread_stack_ptr; */ + + lw sp, 8(t1) // Switch to thread stack + + /* Determine the type of stack frame. */ + /* if (*sp) + { */ + + lw t0, 0(sp) // Pickup stack type + beqz t0, _tx_thread_solicited_return // If 0, solicited return + + /* Recover floating point registers. */ +#if defined(__riscv_float_abi_single) + flw f0, 31*4(sp) // Recover ft0 + flw f1, 32*4(sp) // Recover ft1 + flw f2, 33*4(sp) // Recover ft2 + flw f3, 34*4(sp) // Recover ft3 + flw f4, 35*4(sp) // Recover ft4 + flw f5, 36*4(sp) // Recover ft5 + flw f6, 37*4(sp) // Recover ft6 + flw f7, 38*4(sp) // Recover ft7 + flw f8, 39*4(sp) // Recover fs0 + flw f9, 40*4(sp) // Recover fs1 + flw f10, 41*4(sp) // Recover fa0 + flw f11, 42*4(sp) // Recover fa1 + flw f12, 43*4(sp) // Recover fa2 + flw f13, 44*4(sp) // Recover fa3 + flw f14, 45*4(sp) // Recover fa4 + flw f15, 46*4(sp) // Recover fa5 + flw f16, 47*4(sp) // Recover fa6 + flw f17, 48*4(sp) // Recover fa7 + flw f18, 49*4(sp) // Recover fs2 + flw f19, 50*4(sp) // Recover fs3 + flw f20, 51*4(sp) // Recover fs4 + flw f21, 52*4(sp) // Recover fs5 + flw f22, 53*4(sp) // Recover fs6 + flw f23, 54*4(sp) // Recover fs7 + flw f24, 55*4(sp) // Recover fs8 + flw f25, 56*4(sp) // Recover fs9 + flw f26, 57*4(sp) // Recover fs10 + flw f27, 58*4(sp) // Recover fs11 + flw f28, 59*4(sp) // Recover ft8 + flw f29, 60*4(sp) // Recover ft9 + flw f30, 61*4(sp) // Recover ft10 + flw f31, 62*4(sp) // Recover ft11 + lw t0, 63*4(sp) // Recover fcsr + csrw fcsr, t0 // Restore fcsr +#elif defined(__riscv_float_abi_double) + fld f0, 31*4(sp) // Recover ft0 + fld f1, 32*4(sp) // Recover ft1 + fld f2, 33*4(sp) // Recover ft2 + fld f3, 34*4(sp) // Recover ft3 + fld f4, 35*4(sp) // Recover ft4 + fld f5, 36*4(sp) // Recover ft5 + fld f6, 37*4(sp) // Recover ft6 + fld f7, 38*4(sp) // Recover ft7 + fld f8, 39*4(sp) // Recover fs0 + fld f9, 40*4(sp) // Recover fs1 + fld f10, 41*4(sp) // Recover fa0 + fld f11, 42*4(sp) // Recover fa1 + fld f12, 43*4(sp) // Recover fa2 + fld f13, 44*4(sp) // Recover fa3 + fld f14, 45*4(sp) // Recover fa4 + fld f15, 46*4(sp) // Recover fa5 + fld f16, 47*4(sp) // Recover fa6 + fld f17, 48*4(sp) // Recover fa7 + fld f18, 49*4(sp) // Recover fs2 + fld f19, 50*4(sp) // Recover fs3 + fld f20, 51*4(sp) // Recover fs4 + fld f21, 52*4(sp) // Recover fs5 + fld f22, 53*4(sp) // Recover fs6 + fld f23, 54*4(sp) // Recover fs7 + fld f24, 55*4(sp) // Recover fs8 + fld f25, 56*4(sp) // Recover fs9 + fld f26, 57*4(sp) // Recover fs10 + fld f27, 58*4(sp) // Recover fs11 + fld f28, 59*4(sp) // Recover ft8 + fld f29, 60*4(sp) // Recover ft9 + fld f30, 61*4(sp) // Recover ft10 + fld f31, 62*4(sp) // Recover ft11 + lw t0, 63*4(sp) // Recover fcsr + csrw fcsr, t0 // Restore fcsr +#endif + + /* Recover standard registers. */ + + lw t0, 30*4(sp) // Recover mepc + csrw mepc, t0 // Setup mepc + + li t0, 0x1880 // Prepare mstatus: MPP=Machine(0x1800) | MPIE(0x80) +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + li t1, 0x2000 // Set FS bits for FP state + or t0, t0, t1 +#endif + csrw mstatus, t0 // Set mstatus + + lw ra, 28*4(sp) // Recover return address + lw t0, 19*4(sp) // Recover t0 + lw t1, 18*4(sp) // Recover t1 + lw t2, 17*4(sp) // Recover t2 + lw s0, 12*4(sp) // Recover s0 + lw x9, 11*4(sp) // Recover s1 + lw a0, 27*4(sp) // Recover a0 + lw a1, 26*4(sp) // Recover a1 + lw a2, 25*4(sp) // Recover a2 + lw a3, 24*4(sp) // Recover a3 + lw a4, 23*4(sp) // Recover a4 + lw a5, 22*4(sp) // Recover a5 + lw a6, 21*4(sp) // Recover a6 + lw a7, 20*4(sp) // Recover a7 + lw t3, 16*4(sp) // Recover t3 + lw t4, 15*4(sp) // Recover t4 + lw t5, 14*4(sp) // Recover t5 + lw t6, 13*4(sp) // Recover t6 + lw x18, 10*4(sp) // Recover s2 + lw x19, 9*4(sp) // Recover s3 + lw x20, 8*4(sp) // Recover s4 + lw x21, 7*4(sp) // Recover s5 + lw x22, 6*4(sp) // Recover s6 + lw x23, 5*4(sp) // Recover s7 + lw x24, 4*4(sp) // Recover s8 + lw x25, 3*4(sp) // Recover s9 + lw x26, 2*4(sp) // Recover s10 + lw x27, 1*4(sp) // Recover s11 + +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi sp, sp, 65*4 // Recover stack frame - with floating point enabled +#else + addi sp, sp, 32*4 // Recover stack frame - without floating point enabled +#endif + mret // Return to thread + +_tx_thread_solicited_return: + + /* Recover floating point registers. */ +#if defined(__riscv_float_abi_single) + flw f8, 15*4(sp) // Recover fs0 + flw f9, 16*4(sp) // Recover fs1 + flw f18, 17*4(sp) // Recover fs2 + flw f19, 18*4(sp) // Recover fs3 + flw f20, 19*4(sp) // Recover fs4 + flw f21, 20*4(sp) // Recover fs5 + flw f22, 21*4(sp) // Recover fs6 + flw f23, 22*4(sp) // Recover fs7 + flw f24, 23*4(sp) // Recover fs8 + flw f25, 24*4(sp) // Recover fs9 + flw f26, 25*4(sp) // Recover fs10 + flw f27, 26*4(sp) // Recover fs11 + lw t0, 27*4(sp) // Recover fcsr + csrw fcsr, t0 // Restore fcsr +#elif defined(__riscv_float_abi_double) + fld f8, 15*4(sp) // Recover fs0 + fld f9, 16*4(sp) // Recover fs1 + fld f18, 17*4(sp) // Recover fs2 + fld f19, 18*4(sp) // Recover fs3 + fld f20, 19*4(sp) // Recover fs4 + fld f21, 20*4(sp) // Recover fs5 + fld f22, 21*4(sp) // Recover fs6 + fld f23, 22*4(sp) // Recover fs7 + fld f24, 23*4(sp) // Recover fs8 + fld f25, 24*4(sp) // Recover fs9 + fld f26, 25*4(sp) // Recover fs10 + fld f27, 26*4(sp) // Recover fs11 + lw t0, 27*4(sp) // Recover fcsr + csrw fcsr, t0 // Restore fcsr +#endif + + /* Recover standard registers. */ + + lw t0, 14*4(sp) // Recover mstatus + csrw mstatus, t0 // Restore mstatus + + lw ra, 13*4(sp) // Recover return address + lw s0, 12*4(sp) // Recover s0 + lw s1, 11*4(sp) // Recover s1 + lw x18, 10*4(sp) // Recover s2 + lw x19, 9*4(sp) // Recover s3 + lw x20, 8*4(sp) // Recover s4 + lw x21, 7*4(sp) // Recover s5 + lw x22, 6*4(sp) // Recover s6 + lw x23, 5*4(sp) // Recover s7 + lw x24, 4*4(sp) // Recover s8 + lw x25, 3*4(sp) // Recover s9 + lw x26, 2*4(sp) // Recover s10 + lw x27, 1*4(sp) // Recover s11 + +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi sp, sp, 29*4 // Recover stack frame - with floating point enabled +#else + addi sp, sp, 16*4 // Recover stack frame - without floating point enabled +#endif + ret // Return to thread + +/* } */ diff --git a/ports/risc-v32/gnu/src/tx_thread_stack_build.S b/ports/risc-v32/gnu/src/tx_thread_stack_build.S new file mode 100644 index 000000000..36f9b317f --- /dev/null +++ b/ports/risc-v32/gnu/src/tx_thread_stack_build.S @@ -0,0 +1,227 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + + .section .text +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_stack_build RISC-V32/GNU */ +/* 6.4.x */ +/* AUTHOR */ +/* */ +/* Akif Ejaz, 10xEngineers */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function builds a stack frame on the supplied thread's stack. */ +/* The stack frame results in a fake interrupt return to the supplied */ +/* function pointer. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread control blk */ +/* function_ptr Pointer to return function */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_create Create thread service */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 23-12-2025 Akif Ejaz Initial Version 6.4.x */ +/* */ +/**************************************************************************/ +/* VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +{ */ + .global _tx_thread_stack_build +_tx_thread_stack_build: + + /* Build a fake interrupt frame. The form of the fake interrupt stack + on the RISC-V should look like the following after it is built: + Reg Index + Stack Top: 1 0 Interrupt stack frame type + x27 1 Initial s11 + x26 2 Initial s10 + x25 3 Initial s9 + x24 4 Initial s8 + x23 5 Initial s7 + x22 6 Initial s6 + x21 7 Initial s5 + x20 8 Initial s4 + x19 9 Initial s3 + x18 10 Initial s2 + x9 11 Initial s1 + x8 12 Initial s0 + x31 13 Initial t6 + x30 14 Initial t5 + x29 15 Initial t4 + x28 16 Initial t3 + x7 17 Initial t2 + x6 18 Initial t1 + x5 19 Initial t0 + x17 20 Initial a7 + x16 21 Initial a6 + x15 22 Initial a5 + x14 23 Initial a4 + x13 24 Initial a3 + x12 25 Initial a2 + x11 26 Initial a1 + x10 27 Initial a0 + x1 28 Initial ra + -- 29 reserved + mepc 30 Initial mepc +If floating point support: + f0 31 Initial ft0 + f1 32 Initial ft1 + f2 33 Initial ft2 + f3 34 Initial ft3 + f4 35 Initial ft4 + f5 36 Initial ft5 + f6 37 Initial ft6 + f7 38 Initial ft7 + f8 39 Initial fs0 + f9 40 Initial fs1 + f10 41 Initial fa0 + f11 42 Initial fa1 + f12 43 Initial fa2 + f13 44 Initial fa3 + f14 45 Initial fa4 + f15 46 Initial fa5 + f16 47 Initial fa6 + f17 48 Initial fa7 + f18 49 Initial fs2 + f19 50 Initial fs3 + f20 51 Initial fs4 + f21 52 Initial fs5 + f22 53 Initial fs6 + f23 54 Initial fs7 + f24 55 Initial fs8 + f25 56 Initial fs9 + f26 57 Initial fs10 + f27 58 Initial fs11 + f28 59 Initial ft8 + f29 60 Initial ft9 + f30 61 Initial ft10 + f31 62 Initial ft11 + fscr 63 Initial fscr + + Stack Bottom: (higher memory address) */ + + lw t0, 16(a0) // Pickup end of stack area + li t1, ~15 // Build 16-byte alignment mask + and t0, t0, t1 // Make sure 16-byte alignment + + /* Actually build the stack frame. */ + +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi t0, t0, -65*4 +#else + addi t0, t0, -32*4 // Allocate space for the stack frame +#endif + li t1, 1 // Build stack type + sw t1, 0*4(t0) // Place stack type on the top + sw zero, 1*4(t0) // Initial s11 + sw zero, 2*4(t0) // Initial s10 + sw zero, 3*4(t0) // Initial s9 + sw zero, 4*4(t0) // Initial s8 + sw zero, 5*4(t0) // Initial s7 + sw zero, 6*4(t0) // Initial s6 + sw zero, 7*4(t0) // Initial s5 + sw zero, 8*4(t0) // Initial s4 + sw zero, 9*4(t0) // Initial s3 + sw zero, 10*4(t0) // Initial s2 + sw zero, 11*4(t0) // Initial s1 + sw zero, 12*4(t0) // Initial s0 + sw zero, 13*4(t0) // Initial t6 + sw zero, 14*4(t0) // Initial t5 + sw zero, 15*4(t0) // Initial t4 + sw zero, 16*4(t0) // Initial t3 + sw zero, 17*4(t0) // Initial t2 + sw zero, 18*4(t0) // Initial t1 + sw zero, 19*4(t0) // Initial t0 + sw zero, 20*4(t0) // Initial a7 + sw zero, 21*4(t0) // Initial a6 + sw zero, 22*4(t0) // Initial a5 + sw zero, 23*4(t0) // Initial a4 + sw zero, 24*4(t0) // Initial a3 + sw zero, 25*4(t0) // Initial a2 + sw zero, 26*4(t0) // Initial a1 + sw zero, 27*4(t0) // Initial a0 + sw zero, 28*4(t0) // Initial ra + sw a1, 30*4(t0) // Initial mepc (thread entry point) +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + sw zero, 31*4(t0) // Initial ft0 + sw zero, 32*4(t0) // Initial ft1 + sw zero, 33*4(t0) // Initial ft2 + sw zero, 34*4(t0) // Initial ft3 + sw zero, 35*4(t0) // Initial ft4 + sw zero, 36*4(t0) // Initial ft5 + sw zero, 37*4(t0) // Initial ft6 + sw zero, 38*4(t0) // Initial ft7 + sw zero, 39*4(t0) // Initial fs0 + sw zero, 40*4(t0) // Initial fs1 + sw zero, 41*4(t0) // Initial fa0 + sw zero, 42*4(t0) // Initial fa1 + sw zero, 43*4(t0) // Initial fa2 + sw zero, 44*4(t0) // Initial fa3 + sw zero, 45*4(t0) // Initial fa4 + sw zero, 46*4(t0) // Initial fa5 + sw zero, 47*4(t0) // Initial fa6 + sw zero, 48*4(t0) // Initial fa7 + sw zero, 49*4(t0) // Initial fs2 + sw zero, 50*4(t0) // Initial fs3 + sw zero, 51*4(t0) // Initial fs4 + sw zero, 52*4(t0) // Initial fs5 + sw zero, 53*4(t0) // Initial fs6 + sw zero, 54*4(t0) // Initial fs7 + sw zero, 55*4(t0) // Initial fs8 + sw zero, 56*4(t0) // Initial fs9 + sw zero, 57*4(t0) // Initial fs10 + sw zero, 58*4(t0) // Initial fs11 + sw zero, 59*4(t0) // Initial ft8 + sw zero, 60*4(t0) // Initial ft9 + sw zero, 61*4(t0) // Initial ft10 + sw zero, 62*4(t0) // Initial ft11 + csrr a1, fcsr // Read fcsr for initial value + sw a1, 63*4(t0) // Initial fcsr + sw zero, 64*4(t0) // Reserved word (0) +#else + sw zero, 31*4(t0) // Reserved word (0) +#endif + + /* Setup stack pointer. */ + /* thread_ptr -> tx_thread_stack_ptr = t0; */ + + sw t0, 8(a0) // Save stack pointer in thread's + ret // control block and return +/* } */ diff --git a/ports/risc-v32/gnu/src/tx_thread_system_return.S b/ports/risc-v32/gnu/src/tx_thread_system_return.S new file mode 100644 index 000000000..110f6ac1e --- /dev/null +++ b/ports/risc-v32/gnu/src/tx_thread_system_return.S @@ -0,0 +1,174 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + + .section .text +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_system_return RISC-V32/GNU */ +/* 6.4.x */ +/* AUTHOR */ +/* */ +/* Akif Ejaz, 10xEngineers */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is target processor specific. It is used to transfer */ +/* control from a thread back to the system. Only a minimal context */ +/* is saved since the compiler assumes temp registers are going to get */ +/* slicked by a function call anyway. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_schedule Thread scheduling loop */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 23-12-2025 Akif Ejaz Initial Version 6.4.x */ +/* */ +/**************************************************************************/ +/* VOID _tx_thread_system_return(VOID) +{ */ + .global _tx_thread_system_return +_tx_thread_system_return: + + /* Save minimal context on the stack. */ + /* sp -= sizeof(stack_frame); */ + +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi sp, sp, -29*4 // Allocate space on the stack - with floating point enabled +#else + addi sp, sp, -16*4 // Allocate space on the stack - without floating point enabled +#endif + + /* Store floating point preserved registers. */ +#if defined(__riscv_float_abi_single) + fsw f8, 15*4(sp) // Store fs0 + fsw f9, 16*4(sp) // Store fs1 + fsw f18, 17*4(sp) // Store fs2 + fsw f19, 18*4(sp) // Store fs3 + fsw f20, 19*4(sp) // Store fs4 + fsw f21, 20*4(sp) // Store fs5 + fsw f22, 21*4(sp) // Store fs6 + fsw f23, 22*4(sp) // Store fs7 + fsw f24, 23*4(sp) // Store fs8 + fsw f25, 24*4(sp) // Store fs9 + fsw f26, 25*4(sp) // Store fs10 + fsw f27, 26*4(sp) // Store fs11 + csrr t0, fcsr + sw t0, 27*4(sp) // Store fcsr +#elif defined(__riscv_float_abi_double) + fsd f8, 15*4(sp) // Store fs0 + fsd f9, 16*4(sp) // Store fs1 + fsd f18, 17*4(sp) // Store fs2 + fsd f19, 18*4(sp) // Store fs3 + fsd f20, 19*4(sp) // Store fs4 + fsd f21, 20*4(sp) // Store fs5 + fsd f22, 21*4(sp) // Store fs6 + fsd f23, 22*4(sp) // Store fs7 + fsd f24, 23*4(sp) // Store fs8 + fsd f25, 24*4(sp) // Store fs9 + fsd f26, 25*4(sp) // Store fs10 + fsd f27, 26*4(sp) // Store fs11 + csrr t0, fcsr + sw t0, 27*4(sp) // Store fcsr +#endif + + sw zero, 0(sp) // Solicited stack type + sw ra, 13*4(sp) // Save return address + sw s0, 12*4(sp) // Save s0 + sw s1, 11*4(sp) // Save s1 + sw s2, 10*4(sp) // Save s2 + sw s3, 9*4(sp) // Save s3 + sw s4, 8*4(sp) // Save s4 + sw s5, 7*4(sp) // Save s5 + sw s6, 6*4(sp) // Save s6 + sw s7, 5*4(sp) // Save s7 + sw s8, 4*4(sp) // Save s8 + sw s9, 3*4(sp) // Save s9 + sw s10, 2*4(sp) // Save s10 + sw s11, 1*4(sp) // Save s11 + csrr t0, mstatus // Pickup mstatus + sw t0, 14*4(sp) // Save mstatus + + + /* Lockout interrupts. will be enabled in _tx_thread_schedule */ + + csrci mstatus, 0x08 // Disable interrupts (MIE bit 3) + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + + call _tx_execution_thread_exit // Call the thread execution exit function +#endif + + la t0, _tx_thread_current_ptr // Pickup address of pointer + lw t1, 0(t0) // Pickup current thread pointer + la t2, _tx_thread_system_stack_ptr // Pickup stack pointer address + + /* Save current stack and switch to system stack. */ + /* _tx_thread_current_ptr -> tx_thread_stack_ptr = SP; + SP = _tx_thread_system_stack_ptr; */ + + sw sp, 8(t1) // Save stack pointer + lw sp, 0(t2) // Switch to system stack + + /* Determine if the time-slice is active. */ + /* if (_tx_timer_time_slice) + { */ + + la t4, _tx_timer_time_slice // Pickup time slice variable addr + lw t3, 0(t4) // Pickup time slice value + la t2, _tx_thread_schedule // Pickup address of scheduling loop + beqz t3, _tx_thread_dont_save_ts // If no time-slice, don't save it + + /* Save time-slice for the thread and clear the current time-slice. */ + /* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; + _tx_timer_time_slice = 0; */ + + sw t3, 24(t1) // Save current time-slice for thread + sw zero, 0(t4) // Clear time-slice variable + + /* } */ +_tx_thread_dont_save_ts: + + /* Clear the current thread pointer. */ + /* _tx_thread_current_ptr = TX_NULL; */ + + sw x0, 0(t0) // Clear current thread pointer + jr t2 // Return to thread scheduler + +/* } */ diff --git a/ports/risc-v32/gnu/src/tx_timer_interrupt.S b/ports/risc-v32/gnu/src/tx_timer_interrupt.S new file mode 100644 index 000000000..92b5c6b6e --- /dev/null +++ b/ports/risc-v32/gnu/src/tx_timer_interrupt.S @@ -0,0 +1,210 @@ +/*************************************************************************** + * Copyright (c) 2026 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .section .text + .align 4 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_interrupt RISC-V32/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Akif Ejaz, 10xEngineers */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the hardware timer interrupt. This */ +/* processing includes incrementing the system clock and checking for */ +/* time slice and/or timer expiration. If either is found, the */ +/* interrupt context save/restore functions are called along with the */ +/* expiration functions. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_expiration_process Timer expiration processing */ +/* _tx_thread_time_slice Time slice interrupted thread */ +/* */ +/* CALLED BY */ +/* */ +/* interrupt vector */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-20-2023 Akif Ejaz Initial Version 6.2.1 */ +/* */ +/**************************************************************************/ +/* VOID _tx_timer_interrupt(VOID) +{ */ + .global _tx_timer_interrupt +_tx_timer_interrupt: + + /* Increment the system clock. */ + /* _tx_timer_system_clock++; */ + + la t0, _tx_timer_system_clock // Pickup address of system clock + lw t1, 0(t0) // Pickup system clock + la t2, _tx_timer_time_slice // Pickup address of time slice + lw t3, 0(t2) // Pickup time slice + addi t1, t1, 1 // Increment system clock + sw t1, 0(t0) // Store new system clock + li t6, 0 // Clear local expired flag + + /* Test for time-slice expiration. */ + /* if (_tx_timer_time_slice) + { */ + + beqz t3, _tx_timer_no_time_slice // If 0, skip time slice processing + addi t3, t3, -1 // Decrement the time slice + + /* Decrement the time_slice. */ + /* _tx_timer_time_slice--; */ + + sw t3, 0(t2) // Store new time slice + + /* Check for expiration. */ + /* if (_tx_timer_time_slice == 0) */ + + bgtz t3, _tx_timer_no_time_slice // If not 0, has not expired yet + li t1, 1 // Build expired flag + + /* Set the time-slice expired flag. */ + /* _tx_timer_expired_time_slice = TX_TRUE; */ + + la t4, _tx_timer_expired_time_slice // Get address of expired flag + sw t1, 0(t4) // Set expired flag (UINT) + ori t6, t6, 1 // Set local expired flag + + /* } */ + +_tx_timer_no_time_slice: + + /* Test for timer expiration. */ + /* if (*_tx_timer_current_ptr) + { */ + + la t0, _tx_timer_current_ptr // Pickup address of current ptr + lw t1, 0(t0) // Pickup current pointer (word) + lw t3, 0(t1) // Pickup the current timer entry (word) + la t2, _tx_timer_expired // Pickup address of timer expired flag + li t4, 1 // Build TX_TRUE flag + beqz t3, _tx_timer_no_timer // If NULL, no timer has expired + + /* Set expiration flag. */ + /* _tx_timer_expired = TX_TRUE; */ + + ori t6, t6, 2 // Set local expired flag + sw t4, 0(t2) // Set expired flag in memory (UINT) + j _tx_timer_done // Finished timer processing + + + /* } + else + { */ +_tx_timer_no_timer: + + /* No timer expired, increment the timer pointer. */ + /* _tx_timer_current_ptr++; */ + + /* Check for wrap-around. */ + /* if (_tx_timer_current_ptr == _tx_timer_list_end) */ + + la t2, _tx_timer_list_end // Pickup address of list end pointer + lw t3, 0(t2) // Pickup actual list end + addi t1, t1, 4 // Point to next timer entry + sw t1, 0(t0) // Store new timer pointer + bne t1, t3, _tx_timer_skip_wrap // If not same, good pointer + + /* Wrap to beginning of list. */ + /* _tx_timer_current_ptr = _tx_timer_list_start; */ + + la t2, _tx_timer_list_start // Pickup address of list start pointer + lw t4, 0(t2) // Pickup start of the list + sw t4, 0(t0) // Store new timer pointer + + +_tx_timer_skip_wrap: + /* } */ + +_tx_timer_done: + + + /* See if anything has expired. */ + /* if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) + { */ + + beqz t6, _tx_timer_nothing_expired // If nothing expired skip the rest + addi sp, sp, -16 // Allocate some storage on the stack + sw t6, 0(sp) // Save local expired flag + sw ra, 4(sp) // Save ra + + /* Did a timer expire? */ + /* if (_tx_timer_expired) + { */ + + andi t2, t6, 2 // Isolate the timer expired bit + beqz t2, _tx_timer_dont_activate // No, timer not expired + + /* Call the timer expiration processing. */ + /* _tx_timer_expiration_process(void); */ + + call _tx_timer_expiration_process // Call _tx_timer_expiration_process + lw t6, 0(sp) // Recover local expired flag + + /* } */ +_tx_timer_dont_activate: + + /* Did time slice expire? */ + /* if (_tx_timer_expired_time_slice) + { */ + + andi t2, t6, 1 // Is the timer expired bit set? + beqz t2, _tx_timer_not_ts_expiration // If not, skip time slice processing + + /* Time slice interrupted thread. */ + /* _tx_thread_time_slice(); */ + + call _tx_thread_time_slice // Call time slice + + /* } */ + +_tx_timer_not_ts_expiration: + + lw ra, 4(sp) // Recover ra + addi sp, sp, 16 // Recover stack space + /* } */ + +_tx_timer_nothing_expired: + + ret + +/* } */ \ No newline at end of file