Compare commits

...

3 Commits

Author SHA1 Message Date
Ben V. Brown
4c17b0443c Drop stubs 2022-06-20 21:05:41 +10:00
Ben V. Brown
22d0b0d643 Private links 2022-06-20 19:16:09 +10:00
Ben V. Brown
e6a080c33d CMake 2022-06-20 17:45:25 +10:00
91 changed files with 2991 additions and 3070 deletions

4
.gitignore vendored
View File

@@ -176,4 +176,6 @@ fabric.properties
CoreCompileInputs.cache
.vscode/settings.json
source/compile_commands.json
source/compile_commands.json
source/build/
source/null.cpp

View File

@@ -9,7 +9,7 @@ WORKDIR /build
# musl-dev is required for the multi lang firmwares
# clang is required for clang-format (for dev)
RUN apk add --no-cache gcc-riscv-none-elf gcc-arm-none-eabi newlib-riscv-none-elf newlib-arm-none-eabi findutils python3 py3-pip make git musl-dev clang bash clang-extra-tools
RUN apk add --no-cache gcc-riscv-none-elf gcc-arm-none-eabi newlib-riscv-none-elf newlib-arm-none-eabi findutils python3 py3-pip make git musl-dev clang bash clang-extra-tools cmake
# Install Python3 packages

View File

@@ -0,0 +1,9 @@
# which compilers to use for C and C++
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
set(CMAKE_C_COMPILER arm-none-eabi-gcc CACHE INTERNAL "C Compiler")
set(CMAKE_CXX_COMPILER arm-none-eabi-g++ CACHE INTERNAL "C++ Compiler")
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc -x assembler-with-cpp CACHE INTERNAL "ASM Compiler")
set(CMAKE_OBJCOPY arm-none-eabi-objcopy CACHE INTERNAL "Object Copy")
set(CMAKE_OBJDUMP arm-none-eabi-objdump CACHE INTERNAL "Object Dump")

View File

@@ -0,0 +1,6 @@
# core flags
set(CORE_FLAGS "-march=rv32imac -mabi=ilp32 -mcmodel=medany -fsigned-char -fno-builtin -nostartfiles" CACHE INTERNAL "CPU flags")
add_definitions(${CORE_FLAGS})
# link with linker file
target_link_libraries(${elf_file} PUBLIC -T ${CMAKE_CURRENT_SOURCE_DIR}/linkers/gd32vf103.ld)

View File

@@ -0,0 +1,9 @@
# which compilers to use for C and C++
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
set(CMAKE_C_COMPILER riscv-none-elf-gcc CACHE INTERNAL "C Compiler")
set(CMAKE_CXX_COMPILER riscv-none-elf-g++ CACHE INTERNAL "C++ Compiler")
set(CMAKE_ASM_COMPILER riscv-none-elf-gcc -x assembler-with-cpp CACHE INTERNAL "ASM Compiler")
set(CMAKE_OBJCOPY riscv-none-elf-objcopy CACHE INTERNAL "Object Copy")
set(CMAKE_OBJDUMP riscv-none-elf-objdump CACHE INTERNAL "Object Dump")

View File

@@ -0,0 +1,26 @@
# set additional for compiler and linker: optimization and generate map file
set(additional_linker_flags -Wl,-Map=${map_file},--cref,--no-warn-mismatch)
target_link_libraries(${elf_file} PRIVATE ${additional_linker_flags})
# remove unused sections
target_link_libraries(${elf_file} PUBLIC "-Wl,--gc-sections -Wl,--wrap=malloc -Wl,--wrap=free -Wl,--undefined=vTaskSwitchContext -Wl,--undefined=pxCurrentTCB --specs=nosys.specs -Wl,--print-memory-usage -flto")
set(TARGET_FLAGS "-DMODEL_${MODEL}")
set(OPTIM_FLAGS "-Os -flto -finline-small-functions -findirect-inlining -fdiagnostics-color -ffunction-sections -fdata-sections -fshort-enums -fsingle-precision-constant -ffreestanding -fno-common")
message(ERROR "flags >${CORE_FLAGS}<")
# compiler: language specific flags
set(CMAKE_C_FLAGS " ${CORE_FLAGS} ${OPTIM_FLAGS} ${TARGET_FLAGS} -fno-builtin -Wall -std=gnu11 -fdata-sections -ffunction-sections -g3 " CACHE INTERNAL "c compiler flags")
set(CMAKE_CXX_FLAGS " ${CORE_FLAGS} ${OPTIM_FLAGS} ${TARGET_FLAGS} -fno-rtti -fno-exceptions -fno-builtin -Wall -std=gnu++11 -fdata-sections -ffunction-sections -g -ggdb3" CACHE INTERNAL "cxx compiler flags")
set(CMAKE_ASM_FLAGS " ${CORE_FLAGS} ${OPTIM_FLAGS} ${TARGET_FLAGS} -g -ggdb3 -D__USES_CXX" CACHE INTERNAL "asm compiler flags")
# search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

View File

@@ -0,0 +1,6 @@
# core flags
set(CORE_FLAGS "-mthumb -mcpu=cortex-m3 -mlittle-endian -mfloat-abi=soft" CACHE INTERNAL "CPU flags")
add_definitions(${CORE_FLAGS})
# link with linker file
target_link_libraries(${elf_file} PUBLIC -T ${CMAKE_CURRENT_SOURCE_DIR}/linkers/stm32f103.ld)

87
source/CMakeLists.txt Normal file
View File

@@ -0,0 +1,87 @@
cmake_minimum_required(VERSION 3.23)
set(application_name "${MODEL}_${LANG}")
set(elf_file ${application_name}.elf)
set(bin_file ${application_name}.bin)
set(hex_file ${application_name}.hex)
set(map_file ${application_name}.map)
set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/CMake")
if (MODEL STREQUAL TS100 OR MODEL STREQUAL TS80 OR MODEL STREQUAL TS80P)
set(CMAKE_TOOLCHAIN_FILE "CMake/arm-gcc.cmake" CACHE PATH "toolchain file")
include(${CMAKE_TOOLCHAIN_FILE})
elseif(MODEL STREQUAL Pinecil)
set(CMAKE_TOOLCHAIN_FILE "CMake/riscv-gcc.cmake" CACHE PATH "toolchain file")
include(${CMAKE_TOOLCHAIN_FILE})
elseif(MODEL STREQUAL MHP30)
set(CMAKE_TOOLCHAIN_FILE "CMake/arm-gcc.cmake" CACHE PATH "toolchain file")
include(${CMAKE_TOOLCHAIN_FILE})
else()
message(FATAL_ERROR "You must specify a model")
endif()
# Export compile commands for IDE's
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD 11)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
#add_compile_options( -Wall -Werror)
project(IronOS
LANGUAGES C CXX ASM
)
#Setup outputs
project (${application_name} C CXX ASM)
# add sources to elf file
file(WRITE null.cpp "")
add_executable(${elf_file}
null.cpp
)
include_directories(
Core
Middlewares
)
add_subdirectory(Core)
add_subdirectory(Middlewares)
target_link_libraries(${elf_file} PRIVATE BSP mainSource threads FreeRTOS languages BSPImplementation drivers USBPDLib)
if (MODEL STREQUAL TS100 OR MODEL STREQUAL TS80 OR MODEL STREQUAL TS80P)
include(stm32f1)
elseif(MODEL STREQUAL Pinecil)
include(gd32vf1)
elseif(MODEL STREQUAL MHP30)
include(stm32f1)
else()
message(FATAL_ERROR "You must specify a model")
endif()
include(shared-compiler-settings)
# set additional for compiler and linker: optimization and generate map file
set(additional_compiler_flags ${opt_level})
set(additional_linker_flags -Wl,-Map=${map_file},--cref,--no-warn-mismatch)
target_compile_options(${elf_file} PRIVATE ${additional_compiler_flags})
target_link_libraries(${elf_file} PRIVATE ${additional_linker_flags})
# remove unused sections
# create binary and hex files
add_custom_target(${hex_file} DEPENDS ${elf_file} COMMAND ${CMAKE_OBJCOPY} -O ihex ${elf_file} ${hex_file})
add_custom_target(${bin_file} DEPENDS ${elf_file} COMMAND ${CMAKE_OBJCOPY} -O binary ${elf_file} ${bin_file})

View File

@@ -3,7 +3,6 @@
#include "BSP_Power.h"
#include "BSP_QC.h"
#include "Defines.h"
#include "configuration.h"
#include <stdbool.h>
#include <stdint.h>
/*

View File

@@ -0,0 +1,20 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(sources
BSP_Common.c
)
add_library(BSP ${sources})
target_include_directories(BSP PUBLIC .)
target_link_libraries(BSP PUBLIC FreeRTOS)
if (MODEL STREQUAL TS100 OR MODEL STREQUAL TS80 OR MODEL STREQUAL TS80P)
add_subdirectory(Miniware)
elseif(MODEL STREQUAL Pinecil)
add_subdirectory(Pine64)
elseif(MODEL STREQUAL MHP30)
add_subdirectory(MHP30)
else()
message(FATAL_ERROR "You must specify a model")
endif()

View File

@@ -0,0 +1,52 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Vendor/CMSIS/Include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Vendor/CMSIS/Device)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Inc)
set(sources
BSP.cpp
flash.c
fusb_user.cpp
I2C_Wrapper.cpp
IRQ.cpp
port.c
postRTOS.cpp
Power.cpp
preRTOS.cpp
QC_GPIO.cpp
Setup.cpp
startup_stm32f103t8ux.S
stm32f1xx_hal_msp.c
stm32f1xx_hal_timebase_TIM.c
stm32f1xx_it.c
system_stm32f1xx.c
ThermoModel.cpp
# ST code
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_iwdg.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c
)
add_library(BSPImplementation ${sources})
target_include_directories(BSPImplementation PUBLIC . ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/CMSIS/Include ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/CMSIS/Device ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/STM32F1xx_HAL_Driver/Inc)
target_compile_definitions (BSPImplementation PUBLIC "-D STM32F103T8Ux -D STM32F1 -D STM32 -D USE_HAL_DRIVER -D STM32F103xB -D USE_RTOS_SYSTICK -D GCC_ARMCM3 -D ARM_MATH_CM3 -D STM32F10X_MD")
target_link_libraries(BSPImplementation PUBLIC brieflz BSP mainSource drivers)
target_link_libraries(${elf_file} PUBLIC -Wl,--defsym=__FLASH_SIZE__=64k -Wl,--defsym=__BOOTLDR_SIZE__=0x4000)
set(DEVICE_DFU_ADDRESS 0x08004000)
set(DEVICE_DFU_VID_PID 0x1209:0xDB42)

View File

@@ -0,0 +1,344 @@
/**
******************************************************************************
* @file startup_stm32.s
* @author Ac6
* @version V1.0.0
* @date 12-June-2014
******************************************************************************
*/
.syntax unified
.cpu cortex-m3
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
.equ BootRAM, 0xF1E0F85F
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit
CopyDataInit:
ldr r3, =_sidata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4
LoopCopyDataInit:
ldr r0, =_sdata
ldr r3, =_edata
adds r2, r0, r1
cmp r2, r3
bcc CopyDataInit
ldr r2, =_sbss
b LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
movs r3, #0
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
LoopForever:
b LoopForever
.size Reset_Handler, .-Reset_Handler
/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
*
* @param None
* @retval : None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex-M. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word WWDG_IRQHandler
.word PVD_IRQHandler
.word TAMPER_IRQHandler
.word RTC_IRQHandler
.word FLASH_IRQHandler
.word RCC_IRQHandler
.word EXTI0_IRQHandler
.word EXTI1_IRQHandler
.word EXTI2_IRQHandler
.word EXTI3_IRQHandler
.word EXTI4_IRQHandler
.word DMA1_Channel1_IRQHandler
.word DMA1_Channel2_IRQHandler
.word DMA1_Channel3_IRQHandler
.word DMA1_Channel4_IRQHandler
.word DMA1_Channel5_IRQHandler
.word DMA1_Channel6_IRQHandler
.word DMA1_Channel7_IRQHandler
.word ADC1_2_IRQHandler
.word USB_HP_CAN1_TX_IRQHandler
.word USB_LP_CAN1_RX0_IRQHandler
.word CAN1_RX1_IRQHandler
.word CAN1_SCE_IRQHandler
.word EXTI9_5_IRQHandler
.word TIM1_BRK_IRQHandler
.word TIM1_UP_IRQHandler
.word TIM1_TRG_COM_IRQHandler
.word TIM1_CC_IRQHandler
.word TIM2_IRQHandler
.word TIM3_IRQHandler
.word TIM4_IRQHandler
.word I2C1_EV_IRQHandler
.word I2C1_ER_IRQHandler
.word I2C2_EV_IRQHandler
.word I2C2_ER_IRQHandler
.word SPI1_IRQHandler
.word SPI2_IRQHandler
.word USART1_IRQHandler
.word USART2_IRQHandler
.word USART3_IRQHandler
.word EXTI15_10_IRQHandler
.word RTC_Alarm_IRQHandler
.word USBWakeUp_IRQHandler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word BootRAM /* @0x108. This is for boot in RAM mode for
STM32F10x Medium Density devices. */
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
.weak PVD_IRQHandler
.thumb_set PVD_IRQHandler,Default_Handler
.weak TAMPER_IRQHandler
.thumb_set TAMPER_IRQHandler,Default_Handler
.weak RTC_IRQHandler
.thumb_set RTC_IRQHandler,Default_Handler
.weak FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler
.weak RCC_IRQHandler
.thumb_set RCC_IRQHandler,Default_Handler
.weak EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler
.weak EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler
.weak EXTI2_IRQHandler
.thumb_set EXTI2_IRQHandler,Default_Handler
.weak EXTI3_IRQHandler
.thumb_set EXTI3_IRQHandler,Default_Handler
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
.weak DMA1_Channel1_IRQHandler
.thumb_set DMA1_Channel1_IRQHandler,Default_Handler
.weak DMA1_Channel2_IRQHandler
.thumb_set DMA1_Channel2_IRQHandler,Default_Handler
.weak DMA1_Channel3_IRQHandler
.thumb_set DMA1_Channel3_IRQHandler,Default_Handler
.weak DMA1_Channel4_IRQHandler
.thumb_set DMA1_Channel4_IRQHandler,Default_Handler
.weak DMA1_Channel5_IRQHandler
.thumb_set DMA1_Channel5_IRQHandler,Default_Handler
.weak DMA1_Channel6_IRQHandler
.thumb_set DMA1_Channel6_IRQHandler,Default_Handler
.weak DMA1_Channel7_IRQHandler
.thumb_set DMA1_Channel7_IRQHandler,Default_Handler
.weak ADC1_2_IRQHandler
.thumb_set ADC1_2_IRQHandler,Default_Handler
.weak USB_HP_CAN1_TX_IRQHandler
.thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler
.weak USB_LP_CAN1_RX0_IRQHandler
.thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler
.weak CAN1_RX1_IRQHandler
.thumb_set CAN1_RX1_IRQHandler,Default_Handler
.weak CAN1_SCE_IRQHandler
.thumb_set CAN1_SCE_IRQHandler,Default_Handler
.weak EXTI9_5_IRQHandler
.thumb_set EXTI9_5_IRQHandler,Default_Handler
.weak TIM1_BRK_IRQHandler
.thumb_set TIM1_BRK_IRQHandler,Default_Handler
.weak TIM1_UP_IRQHandler
.thumb_set TIM1_UP_IRQHandler,Default_Handler
.weak TIM1_TRG_COM_IRQHandler
.thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
.weak TIM2_IRQHandler
.thumb_set TIM2_IRQHandler,Default_Handler
.weak TIM3_IRQHandler
.thumb_set TIM3_IRQHandler,Default_Handler
.weak TIM4_IRQHandler
.thumb_set TIM4_IRQHandler,Default_Handler
.weak I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak I2C2_EV_IRQHandler
.thumb_set I2C2_EV_IRQHandler,Default_Handler
.weak I2C2_ER_IRQHandler
.thumb_set I2C2_ER_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak USART3_IRQHandler
.thumb_set USART3_IRQHandler,Default_Handler
.weak EXTI15_10_IRQHandler
.thumb_set EXTI15_10_IRQHandler,Default_Handler
.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
.weak USBWakeUp_IRQHandler
.thumb_set USBWakeUp_IRQHandler,Default_Handler
/************************ (C) COPYRIGHT Ac6 *****END OF FILE****/

View File

@@ -0,0 +1,63 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Vendor/NMSIS/Core/Include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Vendor/OS/FreeRTOS/Source/portable/GCC)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/)
set(sources
# Vendor Code
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/OS/FreeRTOS/Source/portable/GCC/portasm.S
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/OS/FreeRTOS/Source/portable/GCC/port.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/gd32vf103_soc.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/system_gd32vf103.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_adc.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_bkp.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_crc.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_dac.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_dbg.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_dma.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_eclic.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_exmc.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_exti.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_fmc.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_fwdgt.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_gpio.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_i2c.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_pmu.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_rcu.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_rtc.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_spi.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_timer.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_usart.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/gd32vf103_wwdgt.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Drivers/n200_func.c
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/GCC/intexc_gd32vf103.S
${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/GCC/startup_gd32vf103.S
BSP.cpp
Debug.cpp
I2C_Wrapper.cpp
postRTOS.cpp
preRTOS.cpp
flash.c
fusb_user.cpp
ThermoModel.cpp
IRQ.cpp
Setup.cpp
Power.cpp
QC_GPIO.cpp
)
add_library(BSPImplementation ${sources})
target_include_directories(BSPImplementation PUBLIC . ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/NMSIS/Core/Include ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/OS/FreeRTOS/Source/portable/GCC ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Include ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/ ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/)
target_compile_definitions (BSPImplementation PUBLIC -DRTOS_FREERTOS -DDOWNLOAD_MODE=DOWNLOAD_MODE_FLASHXIP -DUSE_RTOS_SYSTICK -DVECT_TAB_OFFSET=0U)
target_link_libraries(BSPImplementation PRIVATE brieflz BSP threads drivers mainSource)
target_link_libraries(${elf_file} PUBLIC -Wl,--defsym=__FLASH_SIZE__=128k -Wl,--defsym=__BOOTLDR_SIZE__=0)
set(DEVICE_DFU_ADDRESS 0x08000000)
set(DEVICE_DFU_VID_PID 0x28E9:0x0189)

View File

@@ -2,10 +2,12 @@
#define FREERTOS_CONFIG_H
#include "nuclei_sdk_soc.h"
#include <stdint.h>
#define configISR_STACK_SIZE_WORDS 1024
#define configCLINT_BASE_ADDRESS 0
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configUSE_TICKLESS_IDLE 0
#define configCPU_CLOCK_HZ ((uint32_t)SystemCoreClock)
#define configCPU_CLOCK_HZ (108000000U / 4)
#define configRTC_CLOCK_HZ ((uint32_t)32768)
#define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES (4)

View File

@@ -8,6 +8,7 @@
#include "IRQ.h"
#include "Pins.h"
#include "configuration.h"
#include "main.hpp"
volatile uint8_t i2c_read_process = 0;
volatile uint8_t i2c_write_process = 0;
volatile uint8_t i2c_slave_address = 0;

View File

@@ -0,0 +1,19 @@
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
#define __FREERTOS_RISC_V_EXTENSIONS_H__
#define portasmHAS_CLINT 0
#define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */
.macro portasmSAVE_ADDITIONAL_REGISTERS
/* No additional registers to save, so this macro does nothing. */
.endm
/* Restore the additional registers found on the Pulpino. */
.macro portasmRESTORE_ADDITIONAL_REGISTERS
/* No additional registers to restore, so this macro does nothing. */
.endm
/* hkim temporary workaround */
#define portasmMCAUSE_MASK 0xfff
#define portasmHANDLE_INTERRUPT irq_entry
#endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */

View File

@@ -26,55 +26,18 @@
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the Nuclei N/NX Processor port.
* Implementation of functions defined in portable.h for the RISC-V RV32 port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "portmacro.h"
#include "task.h"
#include <stdio.h>
//#define ENABLE_KERNEL_DEBUG
#ifdef ENABLE_KERNEL_DEBUG
#define FREERTOS_PORT_DEBUG(...) printf(__VA_ARGS__)
#else
#define FREERTOS_PORT_DEBUG(...)
#ifndef configCLINT_BASE_ADDRESS
#warning configCLINT_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a Core Local Interrupter (CLINT) then set configCLINT_BASE_ADDRESS to the CLINT base address. Otherwise set configCLINT_BASE_ADDRESS to 0.
#endif
#ifndef configSYSTICK_CLOCK_HZ
#define configSYSTICK_CLOCK_HZ SOC_TIMER_FREQ
#endif
#ifndef configKERNEL_INTERRUPT_PRIORITY
#define configKERNEL_INTERRUPT_PRIORITY 0
#endif
#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY
// See function prvCheckMaxSysCallPrio and prvCalcMaxSysCallMTH
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 255
#endif
/* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER (18)
#define SYSTICK_TICK_CONST (configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ)
/* Masks off all bits but the ECLIC MTH bits in the MTH register. */
#define portMTH_MASK (0xFFUL)
/* Constants required to set up the initial stack. */
#define portINITIAL_MSTATUS (MSTATUS_MPP | MSTATUS_MPIE | MSTATUS_FS_INITIAL)
#define portINITIAL_EXC_RETURN (0xfffffffd)
/* The systick is a 64-bit counter. */
#define portMAX_BIT_NUMBER (SysTimer_MTIMER_Msk)
/* A fiddle factor to estimate the number of SysTick counts that would have
occurred while the SysTick counter is stopped during tickless idle
calculations. */
#define portMISSED_COUNTS_FACTOR (45UL)
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case it messes up unwinding of the stack in the
debugger. */
@@ -84,574 +47,145 @@ debugger. */
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/* The stack used by interrupt service routines. Set configISR_STACK_SIZE_WORDS
to use a statically allocated array as the interrupt stack. Alternative leave
configISR_STACK_SIZE_WORDS undefined and update the linker script so that a
linker variable names __freertos_irq_stack_top has the same value as the top
of the stack used by main. Using the linker script method will repurpose the
stack that was used by main before the scheduler was started for use as the
interrupt stack after the scheduler has started. */
#ifdef configISR_STACK_SIZE_WORDS
static __attribute__((aligned(16))) StackType_t xISRStack[configISR_STACK_SIZE_WORDS] = {0};
const StackType_t xISRStackTop = (StackType_t) & (xISRStack[(configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK) - 1]);
#else
extern const uint32_t __freertos_irq_stack_top[];
const StackType_t xISRStackTop = (StackType_t)__freertos_irq_stack_top;
#endif
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
* generate the tick interrupt.
*/
void vPortSetupTimerInterrupt(void);
/*
* Exception handlers.
*/
void xPortSysTickHandler(void);
/*
* Start first task is a separate function so it can be tested in isolation.
*/
extern void prvPortStartFirstTask(void) __attribute__((naked));
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError(void);
#define xPortSysTickHandler eclic_mtip_handler
void vPortSetupTimerInterrupt(void) __attribute__((weak));
/*-----------------------------------------------------------*/
/* Each task maintains its own interrupt status in the critical nesting
variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/* Used to program the machine timer compare register. */
uint64_t ullNextTime = 0ULL;
const uint64_t *pullNextTime = &ullNextTime;
const size_t uxTimerIncrementsForOneTick = (size_t)(configCPU_CLOCK_HZ / configTICK_RATE_HZ); /* Assumes increment won't go over 32-bits. */
volatile uint64_t *const pullMachineTimerCompareRegister = (volatile uint64_t *const)(configCLINT_BASE_ADDRESS + 0x4000);
/*
* Record the real MTH calculated by the configMAX_SYSCALL_INTERRUPT_PRIORITY
* The configMAX_SYSCALL_INTERRUPT_PRIORITY is not the left-aligned level value,
* See equations below:
* Level Bits number: lvlbits = min(nlbits, CLICINTCTLBITS)
* Left align Bits number: lfabits = 8-lvlbits
* 0 < configMAX_SYSCALL_INTERRUPT_PRIORITY <= (2^lvlbits-1)
* uxMaxSysCallMTH = (configMAX_SYSCALL_INTERRUPT_PRIORITY << lfabits) | ((2^lfabits)-1)
* If nlbits = 3, CLICINTCTLBITS=3, then lvlbits = 3, lfabits = 5
* Set configMAX_SYSCALL_INTERRUPT_PRIORITY to 6
* Then uxMaxSysCallMTH = (6<<5) | (2^5 - 1) = 223
*
* See function prvCheckMaxSysCallPrio and prvCalcMaxSysCallMTH
*/
uint8_t uxMaxSysCallMTH = 255;
/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task
stack checking. A problem in the ISR stack will trigger an assert, not call the
stack overflow hook function (because the stack overflow hook is specific to a
task stack, not the ISR stack). */
#if (configCHECK_FOR_STACK_OVERFLOW > 2)
#warning This path not tested, or even compiled yet.
/* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for
the task stacks, and so will legitimately appear in many positions within
the ISR stack. */
#define portISR_STACK_FILL_BYTE 0xee
/*
* The number of SysTick increments that make up one tick period.
*/
#if (configUSE_TICKLESS_IDLE == 1)
static TickType_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
static const uint8_t ucExpectedStackBytes[]
= {portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE,
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE,
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE};
/*
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
#if (configUSE_TICKLESS_IDLE == 1)
static TickType_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
#if (configUSE_TICKLESS_IDLE == 1)
static TickType_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/
#if (configASSERT_DEFINED == 1)
static uint8_t ucMaxSysCallPriority = 0;
#endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/
/*
* See header file for description.
* As per the standard RISC-V ABI pxTopcOfStack is passed in in a0, pxCode in
* a1, and pvParameters in a2. The new top of stack is passed out in a0.
*
* RISC-V maps registers to ABI names as follows (X1 to X31 integer registers
* for the 'I' profile, X1 to X15 for the 'E' profile, currently I assumed).
*
* Register ABI Name Description Saver
* x0 zero Hard-wired zero -
* x1 ra Return address Caller
* x2 sp Stack pointer Callee
* x3 gp Global pointer -
* x4 tp Thread pointer -
* x5-7 t0-2 Temporaries Caller
* x8 s0/fp Saved register/Frame pointer Callee
* x9 s1 Saved register Callee
* x10-11 a0-1 Function Arguments/return values Caller
* x12-17 a2-7 Function arguments Caller
* x18-27 s2-11 Saved registers Callee
* x28-31 t3-6 Temporaries Caller
*
* The RISC-V context is saved RTOS tasks in the following stack frame,
* where the global and thread pointers are currently assumed to be constant so
* are not saved:
*
* mstatus
* #ifndef __riscv_32e
* x31
* x30
* x29
* x28
* x27
* x26
* x25
* x24
* x23
* x22
* x21
* x20
* x19
* x18
* x17
* x16
* #endif
* x15
* x14
* x13
* x12
* x11
* pvParameters
* x9
* x8
* x7
* x6
* x5
* portTASK_RETURN_ADDRESS
* pxCode
*/
StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) {
/* Simulate the stack frame as it would be created by a context switch
interrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_MSTATUS; /* MSTATUS */
/* Save code space by skipping register initialisation. */
#ifndef __riscv_32e
pxTopOfStack -= 22; /* X11 - X31. */
#define portCHECK_ISR_STACK() configASSERT((memcmp((void *)xISRStack, (void *)ucExpectedStackBytes, sizeof(ucExpectedStackBytes)) == 0))
#else
pxTopOfStack -= 6; /* X11 - X15. */
#endif
*pxTopOfStack = (StackType_t)pvParameters; /* X10/A0 */
pxTopOfStack -= 6; /* X5 - X9 */
*pxTopOfStack = (StackType_t)portTASK_RETURN_ADDRESS; /* RA, X1 */
/* Define the function away. */
#define portCHECK_ISR_STACK()
#endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */
pxTopOfStack--;
*pxTopOfStack = ((StackType_t)pxCode); /* PC */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
static void prvTaskExitError(void) {
volatile uint32_t ulDummy = 0;
#if (configCLINT_BASE_ADDRESS != 0)
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
void vPortSetupTimerInterrupt(void) {
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
volatile uint32_t *const pulTimeHigh = (volatile uint32_t *const)(configCLINT_BASE_ADDRESS + 0xBFFC);
volatile uint32_t *const pulTimeLow = (volatile uint32_t *const)(configCLINT_BASE_ADDRESS + 0xBFF8);
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT(uxCriticalNesting == ~0UL);
portDISABLE_INTERRUPTS();
while (ulDummy == 0) {
/* This file calls prvTaskExitError() after the scheduler has been
started to remove a compiler warning about the function being defined
but never called. ulDummy is used purely to quieten other warnings
about code appearing after this function is called - making ulDummy
volatile makes the compiler think the function could return and
therefore not output an 'unreachable code' warning for code that appears
after it. */
/* Sleep and wait for interrupt */
__WFI();
}
do {
ulCurrentTimeHigh = *pulTimeHigh;
ulCurrentTimeLow = *pulTimeLow;
} while (ulCurrentTimeHigh != *pulTimeHigh);
ullNextTime = (uint64_t)ulCurrentTimeHigh;
ullNextTime <<= 32ULL;
ullNextTime |= (uint64_t)ulCurrentTimeLow;
ullNextTime += (uint64_t)uxTimerIncrementsForOneTick;
*pullMachineTimerCompareRegister = ullNextTime;
/* Prepare the time to use after the next tick interrupt. */
ullNextTime += (uint64_t)uxTimerIncrementsForOneTick;
}
#endif /* ( configCLINT_BASE_ADDRESS != 0 ) */
/*-----------------------------------------------------------*/
static uint8_t prvCheckMaxSysCallPrio(uint8_t max_syscall_prio) {
uint8_t nlbits = __ECLIC_GetCfgNlbits();
uint8_t intctlbits = __ECLIC_INTCTLBITS;
uint8_t lvlbits, temp;
if (nlbits <= intctlbits) {
lvlbits = nlbits;
} else {
lvlbits = intctlbits;
}
temp = ((1 << lvlbits) - 1);
if (max_syscall_prio > temp) {
max_syscall_prio = temp;
}
return max_syscall_prio;
}
static uint8_t prvCalcMaxSysCallMTH(uint8_t max_syscall_prio) {
uint8_t nlbits = __ECLIC_GetCfgNlbits();
uint8_t intctlbits = __ECLIC_INTCTLBITS;
uint8_t lvlbits, lfabits;
uint8_t maxsyscallmth = 0;
uint8_t temp;
if (nlbits <= intctlbits) {
lvlbits = nlbits;
} else {
lvlbits = intctlbits;
}
lfabits = 8 - lvlbits;
temp = ((1 << lvlbits) - 1);
if (max_syscall_prio > temp) {
max_syscall_prio = temp;
}
maxsyscallmth = (max_syscall_prio << lfabits) | ((1 << lfabits) - 1);
return maxsyscallmth;
}
/*
* See header file for description.
*/
BaseType_t xPortStartScheduler(void) {
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. */
configASSERT(configMAX_SYSCALL_INTERRUPT_PRIORITY);
/* Get the real MTH should be set to ECLIC MTH register */
uxMaxSysCallMTH = prvCalcMaxSysCallMTH(configMAX_SYSCALL_INTERRUPT_PRIORITY);
FREERTOS_PORT_DEBUG("Max SysCall MTH is set to 0x%x\n", uxMaxSysCallMTH);
extern void xPortStartFirstTask(void);
#if (configASSERT_DEFINED == 1)
{
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = prvCheckMaxSysCallPrio(configMAX_SYSCALL_INTERRUPT_PRIORITY);
FREERTOS_PORT_DEBUG("Max SysCall Priority is set to %d\n", ucMaxSysCallPriority);
}
#endif /* conifgASSERT_DEFINED */
volatile uint32_t mtvec = 0;
__disable_irq();
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
/* Check the least significant two bits of mtvec are 00 - indicating
single vector mode. */
__asm volatile("csrr %0, mtvec" : "=r"(mtvec));
configASSERT((mtvec & 0x03UL) == 0);
/* Check alignment of the interrupt stack - which is the same as the
stack that was being used by main() prior to the scheduler being
started. */
configASSERT((xISRStackTop & portBYTE_ALIGNMENT_MASK) == 0);
}
#endif /* configASSERT_DEFINED */
/* If there is a CLINT then it is ok to use the default implementation
in this file, otherwise vPortSetupTimerInterrupt() must be implemented to
configure whichever clock is to be used to generate the tick interrupt. */
vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
#if (configCLINT_BASE_ADDRESS != 0)
{
/* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11
for external interrupt. _RB_ What happens here when mtime is not present as
with pulpino? */
__asm volatile("csrs mie, %0" ::"r"(0x880));
}
#else
{
/* Enable external interrupts. */
__asm volatile("csrs mie, %0" ::"r"(0x800));
}
#endif /* configCLINT_BASE_ADDRESS */
/* Start the first task. */
prvPortStartFirstTask();
xPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. Call
vTaskSwitchContext() so link time optimisation does not remove the
symbol. */
vTaskSwitchContext();
prvTaskExitError();
/* Should not get here! */
return 0;
/* Should not get here as after calling xPortStartFirstTask() only tasks
should be executing. */
return pdFAIL;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler(void) {
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
configASSERT(uxCriticalNesting == 1000UL);
}
/*-----------------------------------------------------------*/
void vPortEnterCritical(void) {
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */
if (uxCriticalNesting == 1) {
configASSERT((__ECLIC_GetMth() & portMTH_MASK) == uxMaxSysCallMTH);
}
}
/*-----------------------------------------------------------*/
void vPortExitCritical(void) {
configASSERT(uxCriticalNesting);
uxCriticalNesting--;
if (uxCriticalNesting == 0) {
portENABLE_INTERRUPTS();
}
}
/*-----------------------------------------------------------*/
void vPortAssert(int32_t x) {
TaskHandle_t th;
if ((x) == 0) {
taskDISABLE_INTERRUPTS();
#if (INCLUDE_xTaskGetCurrentTaskHandle == 1)
th = xTaskGetCurrentTaskHandle();
if (th) {
printf("Assert in task %s\n", pcTaskGetName(th));
}
#endif
while (1) {
/* Sleep and wait for interrupt */
__WFI();
};
}
}
/*-----------------------------------------------------------*/
void xPortTaskSwitch(void) {
portDISABLE_INTERRUPTS();
/* Clear Software IRQ, A MUST */
SysTimer_ClearSWIRQ();
vTaskSwitchContext();
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
void xPortSysTickHandler(void) {
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already
known. */
portDISABLE_INTERRUPTS();
{
SysTick_Reload(SYSTICK_TICK_CONST);
/* Increment the RTOS tick. */
if (xTaskIncrementTick() != pdFALSE) {
/* A context switch is required. Context switching is performed in
the SWI interrupt. Pend the SWI interrupt. */
portYIELD();
}
}
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
#if (configUSE_TICKLESS_IDLE == 1)
__attribute__((weak)) void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime) {
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
volatile TickType_t xModifiableIdleTime, xTickCountBeforeSleep, XLastLoadValue;
FREERTOS_PORT_DEBUG("Enter TickLess %d\n", (uint32_t)xExpectedIdleTime);
/* Make sure the SysTick reload value does not overflow the counter. */
if (xExpectedIdleTime > xMaximumPossibleSuppressedTicks) {
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
}
/* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
SysTimer_Stop();
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
through one of the tick periods. */
ulReloadValue = (ulTimerCountsForOneTick * (xExpectedIdleTime - 1UL));
if (ulReloadValue > ulStoppedTimerCompensation) {
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */
__disable_irq();
/* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
if (eTaskConfirmSleepModeStatus() == eAbortSleep) {
/* Restart from whatever is left in the count register to complete
this tick period. */
/* Restart SysTick. */
SysTimer_Start();
/* Reset the reload register to the value required for normal tick
periods. */
SysTick_Reload(ulTimerCountsForOneTick);
/* Re-enable interrupts - see comments above the cpsid instruction()
above. */
__enable_irq();
} else {
xTickCountBeforeSleep = xTaskGetTickCount();
/* Set the new reload value. */
SysTick_Reload(ulReloadValue);
/* Get System timer load value before sleep */
XLastLoadValue = SysTimer_GetLoadValue();
/* Restart SysTick. */
SysTimer_Start();
ECLIC_EnableIRQ(SysTimer_IRQn);
__RWMB();
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING(xModifiableIdleTime);
if (xModifiableIdleTime > 0) {
__WFI();
}
configPOST_SLEEP_PROCESSING(xExpectedIdleTime);
/* Re-enable interrupts to allow the interrupt that brought the MCU
out of sleep mode to execute immediately. */
__enable_irq();
/* Make sure interrupt enable is executed */
__RWMB();
__FENCE_I();
__NOP();
/* Disable interrupts again because the clock is about to be stopped
and interrupts that execute while the clock is stopped will increase
any slippage between the time maintained by the RTOS and calendar
time. */
__disable_irq();
/* Disable the SysTick clock. Again,
the time the SysTick is stopped for is accounted for as best it can
be, but using the tickless mode will inevitably result in some tiny
drift of the time maintained by the kernel with respect to calendar
time*/
ECLIC_DisableIRQ(SysTimer_IRQn);
/* Determine if SysTimer Interrupt is not yet happened,
(in which case an interrupt other than the SysTick
must have brought the system out of sleep mode). */
if (SysTimer_GetLoadValue() >= (XLastLoadValue + ulReloadValue)) {
/* As the pending tick will be processed as soon as this
function exits, the tick value maintained by the tick is stepped
forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
FREERTOS_PORT_DEBUG("TickLess - SysTimer Interrupt Entered!\n");
} else {
/* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted rounded to complete tick
periods (not the ulReload value which accounted for part
ticks). */
xModifiableIdleTime = SysTimer_GetLoadValue();
if (xModifiableIdleTime > XLastLoadValue) {
ulCompletedSysTickDecrements = (xModifiableIdleTime - XLastLoadValue);
} else {
ulCompletedSysTickDecrements = (xModifiableIdleTime + portMAX_BIT_NUMBER - XLastLoadValue);
}
/* How many complete tick periods passed while the processor
was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
SysTick_Reload(ulTimerCountsForOneTick);
FREERTOS_PORT_DEBUG("TickLess - External Interrupt Happened!\n");
}
FREERTOS_PORT_DEBUG("End TickLess %d\n", (uint32_t)ulCompleteTickPeriods);
/* Restart SysTick */
vTaskStepTick(ulCompleteTickPeriods);
/* Exit with interrupts enabled. */
ECLIC_EnableIRQ(SysTimer_IRQn);
__enable_irq();
}
/* Not implemented. */
for (;;)
;
}
#endif /* #if configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
void irq_entry(uint32_t mcause) {
uint32_t ulInterruptNumber;
typedef void (*irq_handler_t)(void);
extern const irq_handler_t vector_base[];
/*
* Setup the systick timer to generate the tick interrupts at the required
* frequency.
*/
__attribute__((weak)) void vPortSetupTimerInterrupt(void) {
/* Calculate the constants required to configure the tick interrupt. */
#if (configUSE_TICKLESS_IDLE == 1)
{
ulTimerCountsForOneTick = (SYSTICK_TICK_CONST);
xMaximumPossibleSuppressedTicks = portMAX_BIT_NUMBER / ulTimerCountsForOneTick;
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / (configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ);
FREERTOS_PORT_DEBUG("CountsForOneTick, SuppressedTicks and TimerCompensation: %u, %u, %u\n", (uint32_t)ulTimerCountsForOneTick, (uint32_t)xMaximumPossibleSuppressedTicks,
(uint32_t)ulStoppedTimerCompensation);
}
#endif /* configUSE_TICKLESS_IDLE */
TickType_t ticks = SYSTICK_TICK_CONST;
ulInterruptNumber = mcause & 0xFFF;
/* Make SWI and SysTick the lowest priority interrupts. */
/* Stop and clear the SysTimer. SysTimer as Non-Vector Interrupt */
SysTick_Config(ticks);
ECLIC_DisableIRQ(SysTimer_IRQn);
ECLIC_SetLevelIRQ(SysTimer_IRQn, configKERNEL_INTERRUPT_PRIORITY);
ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
ECLIC_EnableIRQ(SysTimer_IRQn);
/* Set SWI interrupt level to lowest level/priority, SysTimerSW as Vector Interrupt */
ECLIC_SetShvIRQ(SysTimerSW_IRQn, ECLIC_VECTOR_INTERRUPT);
ECLIC_SetLevelIRQ(SysTimerSW_IRQn, configKERNEL_INTERRUPT_PRIORITY);
ECLIC_EnableIRQ(SysTimerSW_IRQn);
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
#if (configASSERT_DEFINED == 1)
void vPortValidateInterruptPriority(void) {
uint32_t ulCurrentInterrupt;
uint8_t ucCurrentPriority;
/* Obtain the number of the currently executing interrupt. */
CSR_MCAUSE_Type mcause = (CSR_MCAUSE_Type)__RV_CSR_READ(CSR_MCAUSE);
/* Make sure current trap type is interrupt */
configASSERT(mcause.b.interrupt == 1);
if (mcause.b.interrupt) {
ulCurrentInterrupt = mcause.b.exccode;
/* Is the interrupt number a user defined interrupt? */
if (ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER) {
/* Look up the interrupt's priority. */
ucCurrentPriority = __ECLIC_GetLevelIRQ(ulCurrentInterrupt);
/* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
ucMaxSysCallPriority calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
ucMaxSysCallPriority.
Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than
ucMaxSysCallPriority.
Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority,
which is guaranteed to be above ucMaxSysCallPriority,
and therefore also guaranteed to be invalid.
FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible.
The following links provide detailed information:
http://www.freertos.org/FAQHelp.html */
configASSERT(ucCurrentPriority <= ucMaxSysCallPriority);
}
if (vector_base[ulInterruptNumber]) {
vector_base[ulInterruptNumber]();
}
}
#endif /* configASSERT_DEFINED */

View File

@@ -1,4 +1,3 @@
/*
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@@ -26,377 +25,402 @@
* 1 tab == 4 spaces!
*/
#include "riscv_encoding.h"
#ifndef __riscv_32e
#define portRegNum 30
/*
* The FreeRTOS kernel's RISC-V port is split between the the code that is
* common across all currently supported RISC-V chips (implementations of the
* RISC-V ISA), and code which tailors the port to a specific RISC-V chip:
*
* + The code that is common to all RISC-V chips is implemented in
* FreeRTOS\Source\portable\GCC\RISC-V-RV32\portASM.S. There is only one
* portASM.S file because the same file is used no matter which RISC-V chip is
* in use.
*
* + The code that tailors the kernel's RISC-V port to a specific RISC-V
* chip is implemented in freertos_risc_v_chip_specific_extensions.h. There
* is one freertos_risc_v_chip_specific_extensions.h that can be used with any
* RISC-V chip that both includes a standard CLINT and does not add to the
* base set of RISC-V registers. There are additional
* freertos_risc_v_chip_specific_extensions.h files for RISC-V implementations
* that do not include a standard CLINT or do add to the base set of RISC-V
* registers.
*
* CARE MUST BE TAKEN TO INCLDUE THE CORRECT
* freertos_risc_v_chip_specific_extensions.h HEADER FILE FOR THE CHIP
* IN USE. To include the correct freertos_risc_v_chip_specific_extensions.h
* header file ensure the path to the correct header file is in the assembler's
* include path.
*
* This freertos_risc_v_chip_specific_extensions.h is for use on RISC-V chips
* that include a standard CLINT and do not add to the base set of RISC-V
* registers.
*
*/
#if __riscv_xlen == 64
#define portWORD_SIZE 8
#define store_x sd
#define load_x ld
#elif __riscv_xlen == 32
#define store_x sw
#define load_x lw
#define portWORD_SIZE 4
#else
#define portRegNum 14
#error Assembler did not define __riscv_xlen
#endif
#define portCONTEXT_SIZE ( portRegNum * REGBYTES )
#include "freertos_risc_v_chip_specific_extensions.h"
.section .text.entry
.align 8
/* Check the freertos_risc_v_chip_specific_extensions.h and/or command line
definitions. */
#ifndef portasmHAS_CLINT
#error freertos_risc_v_chip_specific_extensions.h must define portasmHAS_CLINT to either 1 (CLINT present) or 0 (clint not present).
#endif
.extern xPortTaskSwitch
#ifndef portasmHANDLE_INTERRUPT
#error portasmHANDLE_INTERRUPT must be defined to the function to be called to handle external/peripheral interrupts. portasmHANDLE_INTERRUPT can be defined on the assmbler command line or in the appropriate freertos_risc_v_chip_specific_extensions.h header file.
#endif
/* Only the standard core registers are stored by default. Any additional
registers must be saved by the portasmSAVE_ADDITIONAL_REGISTERS and
portasmRESTORE_ADDITIONAL_REGISTERS macros - which can be defined in a chip
specific version of freertos_risc_v_chip_specific_extensions.h. See the notes
at the top of this file. */
#define portCONTEXT_SIZE ( 30 * portWORD_SIZE )
.global xPortStartFirstTask
.global freertos_risc_v_trap_handler
.global pxPortInitialiseStack
.extern pxCurrentTCB
.global prvPortStartFirstTask
.extern ulPortTrapHandler
.extern vTaskSwitchContext
.extern Timer_IRQHandler
.extern pullMachineTimerCompareRegister
.extern pullNextTime
.extern uxTimerIncrementsForOneTick /* size_t type so 32-bit on 32-bit core and 64-bits on 64-bit core. */
.extern xISRStackTop
/**
* \brief Global interrupt disabled
* \details
* This function disable global interrupt.
* \remarks
* - All the interrupt requests will be ignored by CPU.
/*-----------------------------------------------------------*/
.align 8
.func
freertos_risc_v_trap_handler:
addi sp, sp, -portCONTEXT_SIZE
store_x x1, 1 * portWORD_SIZE( sp )
store_x x5, 2 * portWORD_SIZE( sp )
store_x x6, 3 * portWORD_SIZE( sp )
store_x x7, 4 * portWORD_SIZE( sp )
store_x x8, 5 * portWORD_SIZE( sp )
store_x x9, 6 * portWORD_SIZE( sp )
store_x x10, 7 * portWORD_SIZE( sp )
store_x x11, 8 * portWORD_SIZE( sp )
store_x x12, 9 * portWORD_SIZE( sp )
store_x x13, 10 * portWORD_SIZE( sp )
store_x x14, 11 * portWORD_SIZE( sp )
store_x x15, 12 * portWORD_SIZE( sp )
store_x x16, 13 * portWORD_SIZE( sp )
store_x x17, 14 * portWORD_SIZE( sp )
store_x x18, 15 * portWORD_SIZE( sp )
store_x x19, 16 * portWORD_SIZE( sp )
store_x x20, 17 * portWORD_SIZE( sp )
store_x x21, 18 * portWORD_SIZE( sp )
store_x x22, 19 * portWORD_SIZE( sp )
store_x x23, 20 * portWORD_SIZE( sp )
store_x x24, 21 * portWORD_SIZE( sp )
store_x x25, 22 * portWORD_SIZE( sp )
store_x x26, 23 * portWORD_SIZE( sp )
store_x x27, 24 * portWORD_SIZE( sp )
store_x x28, 25 * portWORD_SIZE( sp )
store_x x29, 26 * portWORD_SIZE( sp )
store_x x30, 27 * portWORD_SIZE( sp )
store_x x31, 28 * portWORD_SIZE( sp )
csrr t0, mstatus /* Required for MPIE bit. */
store_x t0, 29 * portWORD_SIZE( sp )
portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
load_x t0, pxCurrentTCB /* Load pxCurrentTCB. */
store_x sp, 0( t0 ) /* Write sp to first TCB member. */
csrr a0, mcause
csrr a1, mepc
test_if_asynchronous:
srli a2, a0, __riscv_xlen - 1 /* MSB of mcause is 1 if handing an asynchronous interrupt - shift to LSB to clear other bits. */
beq a2, x0, handle_synchronous /* Branch past interrupt handing if not asynchronous. */
store_x a1, 0( sp ) /* Asynch so save unmodified exception return address. */
handle_asynchronous:
#if( portasmHAS_CLINT != 0 )
test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */
addi t0, x0, 1
slli t0, t0, __riscv_xlen - 1 /* LSB is already set, shift into MSB. Shift 31 on 32-bit or 63 on 64-bit cores. */
addi t1, t0, 7 /* 0x8000[]0007 == machine timer interrupt. */
bne a0, t1, test_if_external_interrupt
load_x t0, pullMachineTimerCompareRegister /* Load address of compare register into t0. */
load_x t1, pullNextTime /* Load the address of ullNextTime into t1. */
#if( __riscv_xlen == 32 )
/* Update the 64-bit mtimer compare match value in two 32-bit writes. */
lw t2, 0(t1) /* Load the low word of ullNextTime into t2. */
lw t3, 4(t1) /* Load the high word of ullNextTime into t3. */
sw t2, 0(t0) /* Store low word of ullNextTime into compare register. */
sw t3, 4(t0) /* Store high word of ullNextTime into compare register. */
lw t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
add t4, t0, t2 /* Add the low word of ullNextTime to the timer increments for one tick (assumes timer increment for one tick fits in 32-bits). */
sltu t5, t4, t2 /* See if the sum of low words overflowed (what about the zero case?). */
add t6, t3, t5 /* Add overflow to high word of ullNextTime. */
sw t4, 0(t1) /* Store new low word of ullNextTime. */
sw t6, 4(t1) /* Store new high word of ullNextTime. */
#endif /* __riscv_xlen == 32 */
#if( __riscv_xlen == 64 )
/* Update the 64-bit mtimer compare match value. */
ld t2, 0(t1) /* Load ullNextTime into t2. */
sd t2, 0(t0) /* Store ullNextTime into compare register. */
ld t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
add t4, t0, t2 /* Add ullNextTime to the timer increments for one tick. */
sd t4, 0(t1) /* Store ullNextTime. */
#endif /* __riscv_xlen == 64 */
load_x sp, xISRStackTop /* Switch to ISR stack before function call. */
jal xTaskIncrementTick
beqz a0, processed_source /* Don't switch context if incrementing tick didn't unblock a task. */
jal vTaskSwitchContext
j processed_source
test_if_external_interrupt: /* If there is a CLINT and the mtimer interrupt is not pending then check to see if an external interrupt is pending. */
addi t1, t1, 4 /* 0x80000007 + 4 = 0x8000000b == Machine external interrupt. */
bne a0, t1, as_yet_unhandled /* Something as yet unhandled. */
#endif /* portasmHAS_CLINT */
load_x sp, xISRStackTop /* Switch to ISR stack before function call. */
jal portasmHANDLE_INTERRUPT /* Jump to the interrupt handler if there is no CLINT or if there is a CLINT and it has been determined that an external interrupt is pending. */
j processed_source
handle_synchronous:
addi a1, a1, 4 /* Synchronous so updated exception return address to the instruction after the instruction that generated the exeption. */
store_x a1, 0( sp ) /* Save updated exception return address. */
test_if_environment_call:
li t0, 11 /* 11 == environment call. */
#if( portasmMCAUSE_MASK != 0) // FIXME hkim
li t1, portasmMCAUSE_MASK
and a0, a0, t1
#endif
bne a0, t0, is_exception /* Not an M environment call, so some other exception. */
load_x sp, xISRStackTop /* Switch to ISR stack before function call. */
jal vTaskSwitchContext
j processed_source
is_exception:
ebreak
j is_exception
as_yet_unhandled:
ebreak
j as_yet_unhandled
processed_source:
load_x t1, pxCurrentTCB /* Load pxCurrentTCB. */
load_x sp, 0( t1 ) /* Read sp from first TCB member. */
/* Load mret with the address of the next instruction in the task to run next. */
load_x t0, 0( sp )
csrw mepc, t0
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
/* Load mstatus with the interrupt enable bits used by the task. */
load_x t0, 29 * portWORD_SIZE( sp )
csrw mstatus, t0 /* Required for MPIE bit. */
load_x x1, 1 * portWORD_SIZE( sp )
load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */
load_x x6, 3 * portWORD_SIZE( sp ) /* t1 */
load_x x7, 4 * portWORD_SIZE( sp ) /* t2 */
load_x x8, 5 * portWORD_SIZE( sp ) /* s0/fp */
load_x x9, 6 * portWORD_SIZE( sp ) /* s1 */
load_x x10, 7 * portWORD_SIZE( sp ) /* a0 */
load_x x11, 8 * portWORD_SIZE( sp ) /* a1 */
load_x x12, 9 * portWORD_SIZE( sp ) /* a2 */
load_x x13, 10 * portWORD_SIZE( sp ) /* a3 */
load_x x14, 11 * portWORD_SIZE( sp ) /* a4 */
load_x x15, 12 * portWORD_SIZE( sp ) /* a5 */
load_x x16, 13 * portWORD_SIZE( sp ) /* a6 */
load_x x17, 14 * portWORD_SIZE( sp ) /* a7 */
load_x x18, 15 * portWORD_SIZE( sp ) /* s2 */
load_x x19, 16 * portWORD_SIZE( sp ) /* s3 */
load_x x20, 17 * portWORD_SIZE( sp ) /* s4 */
load_x x21, 18 * portWORD_SIZE( sp ) /* s5 */
load_x x22, 19 * portWORD_SIZE( sp ) /* s6 */
load_x x23, 20 * portWORD_SIZE( sp ) /* s7 */
load_x x24, 21 * portWORD_SIZE( sp ) /* s8 */
load_x x25, 22 * portWORD_SIZE( sp ) /* s9 */
load_x x26, 23 * portWORD_SIZE( sp ) /* s10 */
load_x x27, 24 * portWORD_SIZE( sp ) /* s11 */
load_x x28, 25 * portWORD_SIZE( sp ) /* t3 */
load_x x29, 26 * portWORD_SIZE( sp ) /* t4 */
load_x x30, 27 * portWORD_SIZE( sp ) /* t5 */
load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */
addi sp, sp, portCONTEXT_SIZE
mret
.endfunc
/*-----------------------------------------------------------*/
.align 8
.func
xPortStartFirstTask:
#if( portasmHAS_CLINT != 0 )
/* If there is a clint then interrupts can branch directly to the FreeRTOS
trap handler. Otherwise the interrupt controller will need to be configured
outside of this file. */
la t0, freertos_risc_v_trap_handler
csrw mtvec, t0
#endif /* portasmHAS_CLILNT */
load_x sp, pxCurrentTCB /* Load pxCurrentTCB. */
load_x sp, 0( sp ) /* Read sp from first TCB member. */
load_x x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
load_x t0, 29 * portWORD_SIZE( sp ) /* mstatus */
csrrw x0, mstatus, t0 /* Interrupts enabled from here! */
load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */
load_x x6, 3 * portWORD_SIZE( sp ) /* t1 */
load_x x7, 4 * portWORD_SIZE( sp ) /* t2 */
load_x x8, 5 * portWORD_SIZE( sp ) /* s0/fp */
load_x x9, 6 * portWORD_SIZE( sp ) /* s1 */
load_x x10, 7 * portWORD_SIZE( sp ) /* a0 */
load_x x11, 8 * portWORD_SIZE( sp ) /* a1 */
load_x x12, 9 * portWORD_SIZE( sp ) /* a2 */
load_x x13, 10 * portWORD_SIZE( sp ) /* a3 */
load_x x14, 11 * portWORD_SIZE( sp ) /* a4 */
load_x x15, 12 * portWORD_SIZE( sp ) /* a5 */
load_x x16, 13 * portWORD_SIZE( sp ) /* a6 */
load_x x17, 14 * portWORD_SIZE( sp ) /* a7 */
load_x x18, 15 * portWORD_SIZE( sp ) /* s2 */
load_x x19, 16 * portWORD_SIZE( sp ) /* s3 */
load_x x20, 17 * portWORD_SIZE( sp ) /* s4 */
load_x x21, 18 * portWORD_SIZE( sp ) /* s5 */
load_x x22, 19 * portWORD_SIZE( sp ) /* s6 */
load_x x23, 20 * portWORD_SIZE( sp ) /* s7 */
load_x x24, 21 * portWORD_SIZE( sp ) /* s8 */
load_x x25, 22 * portWORD_SIZE( sp ) /* s9 */
load_x x26, 23 * portWORD_SIZE( sp ) /* s10 */
load_x x27, 24 * portWORD_SIZE( sp ) /* s11 */
load_x x28, 25 * portWORD_SIZE( sp ) /* t3 */
load_x x29, 26 * portWORD_SIZE( sp ) /* t4 */
load_x x30, 27 * portWORD_SIZE( sp ) /* t5 */
load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */
addi sp, sp, portCONTEXT_SIZE
ret
.endfunc
/*-----------------------------------------------------------*/
/*
* Unlike other ports pxPortInitialiseStack() is written in assembly code as it
* needs access to the portasmADDITIONAL_CONTEXT_SIZE constant. The prototype
* for the function is as per the other ports:
* StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters );
*
* As per the standard RISC-V ABI pxTopcOfStack is passed in in a0, pxCode in
* a1, and pvParameters in a2. The new top of stack is passed out in a0.
*
* RISC-V maps registers to ABI names as follows (X1 to X31 integer registers
* for the 'I' profile, X1 to X15 for the 'E' profile, currently I assumed).
*
* Register ABI Name Description Saver
* x0 zero Hard-wired zero -
* x1 ra Return address Caller
* x2 sp Stack pointer Callee
* x3 gp Global pointer -
* x4 tp Thread pointer -
* x5-7 t0-2 Temporaries Caller
* x8 s0/fp Saved register/Frame pointer Callee
* x9 s1 Saved register Callee
* x10-11 a0-1 Function Arguments/return values Caller
* x12-17 a2-7 Function arguments Caller
* x18-27 s2-11 Saved registers Callee
* x28-31 t3-6 Temporaries Caller
*
* The RISC-V context is saved t FreeRTOS tasks in the following stack frame,
* where the global and thread pointers are currently assumed to be constant so
* are not saved:
*
* mstatus
* x31
* x30
* x29
* x28
* x27
* x26
* x25
* x24
* x23
* x22
* x21
* x20
* x19
* x18
* x17
* x16
* x15
* x14
* x13
* x12
* x11
* pvParameters
* x9
* x8
* x7
* x6
* x5
* portTASK_RETURN_ADDRESS
* [chip specific registers go here]
* pxCode
*/
.macro DISABLE_MIE
csrc CSR_MSTATUS, MSTATUS_MIE
.endm
.align 8
.func
pxPortInitialiseStack:
/**
* \brief Macro for context save
* \details
* This macro save ABI defined caller saved registers in the stack.
* \remarks
* - This Macro could use to save context when you enter to interrupt
* or exception
*/
/* Save caller registers */
.macro SAVE_CONTEXT
csrrw sp, CSR_MSCRATCHCSWL, sp
/* Allocate stack space for context saving */
#ifndef __riscv_32e
addi sp, sp, -20*REGBYTES
#else
addi sp, sp, -14*REGBYTES
#endif /* __riscv_32e */
csrr t0, mstatus /* Obtain current mstatus value. */
addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */
slli t1, t1, 4
or t0, t0, t1 /* Set MPIE and MPP bits in mstatus value. */
STORE x1, 0*REGBYTES(sp)
STORE x4, 1*REGBYTES(sp)
STORE x5, 2*REGBYTES(sp)
STORE x6, 3*REGBYTES(sp)
STORE x7, 4*REGBYTES(sp)
STORE x10, 5*REGBYTES(sp)
STORE x11, 6*REGBYTES(sp)
STORE x12, 7*REGBYTES(sp)
STORE x13, 8*REGBYTES(sp)
STORE x14, 9*REGBYTES(sp)
STORE x15, 10*REGBYTES(sp)
#ifndef __riscv_32e
STORE x16, 14*REGBYTES(sp)
STORE x17, 15*REGBYTES(sp)
STORE x28, 16*REGBYTES(sp)
STORE x29, 17*REGBYTES(sp)
STORE x30, 18*REGBYTES(sp)
STORE x31, 19*REGBYTES(sp)
#endif /* __riscv_32e */
.endm
/**
* \brief Macro for restore caller registers
* \details
* This macro restore ABI defined caller saved registers from stack.
* \remarks
* - You could use this macro to restore context before you want return
* from interrupt or exeception
*/
/* Restore caller registers */
.macro RESTORE_CONTEXT
LOAD x1, 0*REGBYTES(sp)
LOAD x4, 1*REGBYTES(sp)
LOAD x5, 2*REGBYTES(sp)
LOAD x6, 3*REGBYTES(sp)
LOAD x7, 4*REGBYTES(sp)
LOAD x10, 5*REGBYTES(sp)
LOAD x11, 6*REGBYTES(sp)
LOAD x12, 7*REGBYTES(sp)
LOAD x13, 8*REGBYTES(sp)
LOAD x14, 9*REGBYTES(sp)
LOAD x15, 10*REGBYTES(sp)
#ifndef __riscv_32e
LOAD x16, 14*REGBYTES(sp)
LOAD x17, 15*REGBYTES(sp)
LOAD x28, 16*REGBYTES(sp)
LOAD x29, 17*REGBYTES(sp)
LOAD x30, 18*REGBYTES(sp)
LOAD x31, 19*REGBYTES(sp)
/* De-allocate the stack space */
addi sp, sp, 20*REGBYTES
#else
/* De-allocate the stack space */
addi sp, sp, 14*REGBYTES
#endif /* __riscv_32e */
csrrw sp, CSR_MSCRATCHCSWL, sp
.endm
/**
* \brief Macro for save necessary CSRs to stack
* \details
* This macro store MCAUSE, MEPC, MSUBM to stack.
*/
.macro SAVE_CSR_CONTEXT
/* Store CSR mcause to stack using pushmcause */
csrrwi x0, CSR_PUSHMCAUSE, 11
/* Store CSR mepc to stack using pushmepc */
csrrwi x0, CSR_PUSHMEPC, 12
/* Store CSR msub to stack using pushmsub */
csrrwi x0, CSR_PUSHMSUBM, 13
.endm
/**
* \brief Macro for restore necessary CSRs from stack
* \details
* This macro restore MSUBM, MEPC, MCAUSE from stack.
*/
.macro RESTORE_CSR_CONTEXT
LOAD x5, 13*REGBYTES(sp)
csrw CSR_MSUBM, x5
LOAD x5, 12*REGBYTES(sp)
csrw CSR_MEPC, x5
LOAD x5, 11*REGBYTES(sp)
csrw CSR_MCAUSE, x5
.endm
/**
* \brief Exception/NMI Entry
* \details
* This function provide common entry functions for exception/nmi.
* \remarks
* This function provide a default exception/nmi entry.
* ABI defined caller save register and some CSR registers
* to be saved before enter interrupt handler and be restored before return.
*/
.section .text.trap
/* In CLIC mode, the exeception entry must be 64bytes aligned */
.align 6
.global exc_entry
exc_entry:
/* Save the caller saving registers (context) */
SAVE_CONTEXT
/* Save the necessary CSR registers */
SAVE_CSR_CONTEXT
/*
* Set the exception handler function arguments
* argument 1: mcause value
* argument 2: current stack point(SP) value
*/
csrr a0, mcause
mv a1, sp
/*
* TODO: Call the exception handler function
* By default, the function template is provided in
* system_Device.c, you can adjust it as you want
*/
call core_exception_handler
/* Restore the necessary CSR registers */
RESTORE_CSR_CONTEXT
/* Restore the caller saving registers (context) */
RESTORE_CONTEXT
/* Return to regular code */
mret
/**
* \brief Non-Vector Interrupt Entry
* \details
* This function provide common entry functions for handling
* non-vector interrupts
* \remarks
* This function provide a default non-vector interrupt entry.
* ABI defined caller save register and some CSR registers need
* to be saved before enter interrupt handler and be restored before return.
*/
.section .text.irq
/* In CLIC mode, the interrupt entry must be 4bytes aligned */
.align 2
.global irq_entry
/* This label will be set to MTVT2 register */
irq_entry:
/* Save the caller saving registers (context) */
SAVE_CONTEXT
/* Save the necessary CSR registers */
SAVE_CSR_CONTEXT
/* This special CSR read/write operation, which is actually
* claim the CLIC to find its pending highest ID, if the ID
* is not 0, then automatically enable the mstatus.MIE, and
* jump to its vector-entry-label, and update the link register
*/
csrrw ra, CSR_JALMNXTI, ra
/* Critical section with interrupts disabled */
DISABLE_MIE
/* Restore the necessary CSR registers */
RESTORE_CSR_CONTEXT
/* Restore the caller saving registers (context) */
RESTORE_CONTEXT
/* Return to regular code */
mret
/* Default Handler for Exceptions / Interrupts */
.global default_intexc_handler
Undef_Handler:
default_intexc_handler:
addi a0, a0, -portWORD_SIZE
store_x t0, 0(a0) /* mstatus onto the stack. */
addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x11-x31. */
store_x a2, 0(a0) /* Task parameters (pvParameters parameter) goes into register X10/a0 on the stack. */
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x5-x9. */
store_x x0, 0(a0) /* Return address onto the stack, could be portTASK_RETURN_ADDRESS */
addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */
chip_specific_stack_frame: /* First add any chip specific registers to the stack frame being created. */
beq t0, x0, 1f /* No more chip specific registers to save. */
addi a0, a0, -portWORD_SIZE /* Make space for chip specific register. */
store_x x0, 0(a0) /* Give the chip specific register an initial value of zero. */
addi t0, t0, -1 /* Decrement the count of chip specific registers remaining. */
j chip_specific_stack_frame /* Until no more chip specific registers. */
1:
j 1b
/* Start the first task. This also clears the bit that indicates the FPU is
in use in case the FPU was used before the scheduler was started - which
would otherwise result in the unnecessary leaving of space in the stack
for lazy saving of FPU registers. */
.align 3
prvPortStartFirstTask:
/* Setup Interrupt Stack using
The stack that was used by main()
before the scheduler is started is
no longer required after the scheduler is started.
Interrupt stack pointer is stored in CSR_MSCRATCH */
la t0, _sp
csrw CSR_MSCRATCH, t0
LOAD sp, pxCurrentTCB /* Load pxCurrentTCB. */
LOAD sp, 0x0(sp) /* Read sp from first TCB member */
/* Pop PC from stack and set MEPC */
LOAD t0, 0 * REGBYTES(sp)
csrw CSR_MEPC, t0
/* Pop mstatus from stack and set it */
LOAD t0, (portRegNum - 1) * REGBYTES(sp)
csrw CSR_MSTATUS, t0
/* Interrupt still disable here */
/* Restore Registers from Stack */
LOAD x1, 1 * REGBYTES(sp) /* RA */
LOAD x5, 2 * REGBYTES(sp)
LOAD x6, 3 * REGBYTES(sp)
LOAD x7, 4 * REGBYTES(sp)
LOAD x8, 5 * REGBYTES(sp)
LOAD x9, 6 * REGBYTES(sp)
LOAD x10, 7 * REGBYTES(sp)
LOAD x11, 8 * REGBYTES(sp)
LOAD x12, 9 * REGBYTES(sp)
LOAD x13, 10 * REGBYTES(sp)
LOAD x14, 11 * REGBYTES(sp)
LOAD x15, 12 * REGBYTES(sp)
#ifndef __riscv_32e
LOAD x16, 13 * REGBYTES(sp)
LOAD x17, 14 * REGBYTES(sp)
LOAD x18, 15 * REGBYTES(sp)
LOAD x19, 16 * REGBYTES(sp)
LOAD x20, 17 * REGBYTES(sp)
LOAD x21, 18 * REGBYTES(sp)
LOAD x22, 19 * REGBYTES(sp)
LOAD x23, 20 * REGBYTES(sp)
LOAD x24, 21 * REGBYTES(sp)
LOAD x25, 22 * REGBYTES(sp)
LOAD x26, 23 * REGBYTES(sp)
LOAD x27, 24 * REGBYTES(sp)
LOAD x28, 25 * REGBYTES(sp)
LOAD x29, 26 * REGBYTES(sp)
LOAD x30, 27 * REGBYTES(sp)
LOAD x31, 28 * REGBYTES(sp)
#endif
addi sp, sp, portCONTEXT_SIZE
mret
.align 2
.global eclic_msip_handler
eclic_msip_handler:
addi sp, sp, -portCONTEXT_SIZE
STORE x1, 1 * REGBYTES(sp) /* RA */
STORE x5, 2 * REGBYTES(sp)
STORE x6, 3 * REGBYTES(sp)
STORE x7, 4 * REGBYTES(sp)
STORE x8, 5 * REGBYTES(sp)
STORE x9, 6 * REGBYTES(sp)
STORE x10, 7 * REGBYTES(sp)
STORE x11, 8 * REGBYTES(sp)
STORE x12, 9 * REGBYTES(sp)
STORE x13, 10 * REGBYTES(sp)
STORE x14, 11 * REGBYTES(sp)
STORE x15, 12 * REGBYTES(sp)
#ifndef __riscv_32e
STORE x16, 13 * REGBYTES(sp)
STORE x17, 14 * REGBYTES(sp)
STORE x18, 15 * REGBYTES(sp)
STORE x19, 16 * REGBYTES(sp)
STORE x20, 17 * REGBYTES(sp)
STORE x21, 18 * REGBYTES(sp)
STORE x22, 19 * REGBYTES(sp)
STORE x23, 20 * REGBYTES(sp)
STORE x24, 21 * REGBYTES(sp)
STORE x25, 22 * REGBYTES(sp)
STORE x26, 23 * REGBYTES(sp)
STORE x27, 24 * REGBYTES(sp)
STORE x28, 25 * REGBYTES(sp)
STORE x29, 26 * REGBYTES(sp)
STORE x30, 27 * REGBYTES(sp)
STORE x31, 28 * REGBYTES(sp)
#endif
/* Push mstatus to stack */
csrr t0, CSR_MSTATUS
STORE t0, (portRegNum - 1) * REGBYTES(sp)
/* Push additional registers */
/* Store sp to task stack */
LOAD t0, pxCurrentTCB
STORE sp, 0(t0)
csrr t0, CSR_MEPC
STORE t0, 0(sp)
jal xPortTaskSwitch
/* Switch task context */
LOAD t0, pxCurrentTCB /* Load pxCurrentTCB. */
LOAD sp, 0x0(t0) /* Read sp from first TCB member */
/* Pop PC from stack and set MEPC */
LOAD t0, 0 * REGBYTES(sp)
csrw CSR_MEPC, t0
/* Pop additional registers */
/* Pop mstatus from stack and set it */
LOAD t0, (portRegNum - 1) * REGBYTES(sp)
csrw CSR_MSTATUS, t0
/* Interrupt still disable here */
/* Restore Registers from Stack */
LOAD x1, 1 * REGBYTES(sp) /* RA */
LOAD x5, 2 * REGBYTES(sp)
LOAD x6, 3 * REGBYTES(sp)
LOAD x7, 4 * REGBYTES(sp)
LOAD x8, 5 * REGBYTES(sp)
LOAD x9, 6 * REGBYTES(sp)
LOAD x10, 7 * REGBYTES(sp)
LOAD x11, 8 * REGBYTES(sp)
LOAD x12, 9 * REGBYTES(sp)
LOAD x13, 10 * REGBYTES(sp)
LOAD x14, 11 * REGBYTES(sp)
LOAD x15, 12 * REGBYTES(sp)
#ifndef __riscv_32e
LOAD x16, 13 * REGBYTES(sp)
LOAD x17, 14 * REGBYTES(sp)
LOAD x18, 15 * REGBYTES(sp)
LOAD x19, 16 * REGBYTES(sp)
LOAD x20, 17 * REGBYTES(sp)
LOAD x21, 18 * REGBYTES(sp)
LOAD x22, 19 * REGBYTES(sp)
LOAD x23, 20 * REGBYTES(sp)
LOAD x24, 21 * REGBYTES(sp)
LOAD x25, 22 * REGBYTES(sp)
LOAD x26, 23 * REGBYTES(sp)
LOAD x27, 24 * REGBYTES(sp)
LOAD x28, 25 * REGBYTES(sp)
LOAD x29, 26 * REGBYTES(sp)
LOAD x30, 27 * REGBYTES(sp)
LOAD x31, 28 * REGBYTES(sp)
#endif
addi sp, sp, portCONTEXT_SIZE
mret
addi a0, a0, -portWORD_SIZE
store_x a1, 0(a0) /* mret value (pxCode parameter) onto the stack. */
ret
.endfunc
/*-----------------------------------------------------------*/

View File

@@ -32,8 +32,6 @@
extern "C" {
#endif
#include "nuclei_sdk_soc.h"
/*-----------------------------------------------------------
* Port specific definitions.
*
@@ -45,61 +43,92 @@ extern "C" {
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE unsigned long
#define portBASE_TYPE long
#define portPOINTER_SIZE_TYPE unsigned long
#if __riscv_xlen == 64
#define portSTACK_TYPE uint64_t
#define portBASE_TYPE int64_t
#define portUBASE_TYPE uint64_t
#define portMAX_DELAY (TickType_t)0xffffffffffffffffUL
#define portPOINTER_SIZE_TYPE uint64_t
#elif __riscv_xlen == 32
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE int32_t
#define portUBASE_TYPE uint32_t
#define portMAX_DELAY (TickType_t)0xffffffffUL
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#else
#error Assembler did not define __riscv_xlen
#endif
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
typedef portBASE_TYPE BaseType_t;
typedef portUBASE_TYPE UBaseType_t;
typedef portUBASE_TYPE TickType_t;
#if (configUSE_16_BIT_TICKS == 1)
typedef uint16_t TickType_t;
#define portMAX_DELAY (TickType_t)0xffff
#else
/* RISC-V TIMER is 64-bit long */
typedef uint64_t TickType_t;
#define portMAX_DELAY (TickType_t)0xFFFFFFFFFFFFFFFFULL
#endif
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH (-1)
#define portTICK_PERIOD_MS ((TickType_t)1000 / configTICK_RATE_HZ)
#ifdef __riscv64
#error This is the RV32 port that has not yet been adapted for 64.
#define portBYTE_ALIGNMENT 16
#else
#define portBYTE_ALIGNMENT 8
#endif
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
#define portYIELD() \
{ \
/* Set a software interrupt(SWI) request to request a context switch. */ \
SysTimer_SetSWIRQ(); \
/* Barriers are normally not required but do ensure the code is completely \
within the specified behaviour for the architecture. */ \
__RWMB(); \
}
extern void vTaskSwitchContext(void);
#define portYIELD() __asm volatile("ecall");
#define portEND_SWITCHING_ISR(xSwitchRequired) \
if (xSwitchRequired != pdFALSE) \
portYIELD()
if (xSwitchRequired) \
vTaskSwitchContext()
#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x)
/*-----------------------------------------------------------*/
/* Critical section management. */
extern void vPortEnterCritical(void);
extern void vPortExitCritical(void);
#define portCRITICAL_NESTING_IN_TCB 1
extern void vTaskEnterCritical(void);
extern void vTaskExitCritical(void);
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedStatusValue) (void)uxSavedStatusValue
#define portDISABLE_INTERRUPTS() __asm volatile("csrc mstatus, 8")
#define portENABLE_INTERRUPTS() __asm volatile("csrs mstatus, 8")
#define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical()
/*-----------------------------------------------------------*/
/* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
#if (configUSE_PORT_OPTIMISED_TASK_SELECTION == 1)
/* Check the configuration. */
#if (configMAX_PRIORITIES > 32)
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif
/* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY(uxPriority, uxReadyPriorities) (uxReadyPriorities) |= (1UL << (uxPriority))
#define portRESET_READY_PRIORITY(uxPriority, uxReadyPriorities) (uxReadyPriorities) &= ~(1UL << (uxPriority))
/*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY(uxTopPriority, uxReadyPriorities) uxTopPriority = (31UL - __builtin_clz(uxReadyPriorities))
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/
@@ -108,24 +137,10 @@ not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters)
/*-----------------------------------------------------------*/
/* Tickless idle/low power functionality. */
#ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime);
#define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) vPortSuppressTicksAndSleep(xExpectedIdleTime)
#endif
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
#ifdef configASSERT
extern void vPortValidateInterruptPriority(void);
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif
/* portNOP() is not required by this port. */
#define portNOP() __NOP()
#define portNOP() __asm volatile(" nop ")
#define portINLINE __inline
@@ -133,37 +148,6 @@ extern void vPortValidateInterruptPriority(void);
#define portFORCE_INLINE inline __attribute__((always_inline))
#endif
/* This variable should not be set in any of the FreeRTOS application
only used internal of FreeRTOS Port code */
extern uint8_t uxMaxSysCallMTH;
/*-----------------------------------------------------------*/
portFORCE_INLINE static void vPortRaiseBASEPRI(void) {
ECLIC_SetMth(uxMaxSysCallMTH);
__RWMB();
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static uint8_t ulPortRaiseBASEPRI(void) {
uint8_t ulOriginalBASEPRI;
ulOriginalBASEPRI = ECLIC_GetMth();
ECLIC_SetMth(uxMaxSysCallMTH);
__RWMB();
/* This return might not be reached but is necessary to prevent compiler
warnings. */
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static void vPortSetBASEPRI(uint8_t ulNewMaskValue) {
ECLIC_SetMth(ulNewMaskValue);
__RWMB();
}
/*-----------------------------------------------------------*/
#define portMEMORY_BARRIER() __asm volatile("" ::: "memory")
#ifdef __cplusplus

View File

@@ -1,48 +0,0 @@
adapter_khz 100
reset_config srst_only
adapter_nsrst_assert_width 100
interface cmsis-dap
transport select jtag
adapter_khz 100
autoexit true
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x1e200a6d
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 20480 -work-area-backup 0
# Work-area is a space in RAM used for flash programming
if { [info exists WORKAREASIZE] } {
set _WORKAREASIZE $WORKAREASIZE
} else {
set _WORKAREASIZE 0x5000
}
# Allow overriding the Flash bank size
if { [info exists FLASH_SIZE] } {
set _FLASH_SIZE $FLASH_SIZE
} else {
# autodetect size
set _FLASH_SIZE 0
}
# flash size will be probed
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME gd32vf103 0x08000000 0 0 0 $_TARGETNAME
# Expose Nuclei self-defined CSRS range 770-800,835-850,1984-2032,2064-2070
# See https://github.com/riscv/riscv-gnu-toolchain/issues/319#issuecomment-358397306
# Then user can view the csr register value in gdb using: info reg csr775 for CSR MTVT(0x307)
riscv expose_csrs 770-800,835-850,1984-2032,2064-2070
riscv set_reset_timeout_sec 1
init
halt

View File

@@ -1,4 +0,0 @@
#include "stub.h"
#include <errno.h>
int _close(int fd) { return _stub(EBADF); }

View File

@@ -1,6 +0,0 @@
#include "stub.h"
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
int _fstat(int fd, struct stat *st) { return _stub(EBADF); }

View File

@@ -1,13 +0,0 @@
#include "nuclei_sdk_soc.h"
#include <errno.h>
#include <sys/time.h>
int _gettimeofday(struct timeval *tp, void *tzp) {
uint64_t cycles;
cycles = __get_rv_cycle();
tp->tv_sec = cycles / SystemCoreClock;
tp->tv_usec = (cycles % SystemCoreClock) * 1000000 / SystemCoreClock;
return 0;
}

View File

@@ -1,11 +0,0 @@
/* See LICENSE of license details. */
#include <unistd.h>
int _isatty(int fd) {
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
return 1;
}
return 0;
}

View File

@@ -1,6 +0,0 @@
#include "stub.h"
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
off_t _lseek(int fd, off_t ptr, int dir) { return _stub(EBADF); }

View File

@@ -1,9 +0,0 @@
#include "gd32vf103_usart.h"
#include <errno.h>
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h>
// #define UART_AUTO_ECHO
ssize_t _read(int fd, void *ptr, size_t len) { return -1; }

View File

@@ -1,18 +0,0 @@
/* See LICENSE of license details. */
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
void *_sbrk(ptrdiff_t incr) {
extern char _end[];
extern char _heap_end[];
static char *curbrk = _end;
if ((curbrk + incr < _end) || (curbrk + incr > _heap_end)) {
return NULL - 1;
}
curbrk += incr;
return curbrk - incr;
}

View File

@@ -1,2 +0,0 @@
static inline int _stub(int err) { return -1; }

View File

@@ -1,6 +1,5 @@
#ifndef CONFIGURATION_H_
#define CONFIGURATION_H_
#include "Settings.h"
#include <stdint.h>
/**
* Configuration.h

View File

@@ -0,0 +1,6 @@
add_subdirectory(brieflz)
add_subdirectory(BSP)
add_subdirectory(Drivers)
add_subdirectory(LangSupport)
add_subdirectory(Src)
add_subdirectory(Threads)

View File

@@ -2,6 +2,7 @@
#include "BSP.h"
#include "Buttons.hpp"
#include "OLED.hpp"
#include "Settings.h"
#include "cmsis_os.h"
#define LOGO_PAGE_LENGTH 1024

View File

@@ -0,0 +1,25 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(sources
BMA223.cpp
BootLogo.cpp
Buttons.cpp
I2CBB.cpp
LIS2DH12.cpp
MMA8652FC.cpp
MSA301.cpp
OLED.cpp
SC7A20.cpp
Si7210.cpp
TipThermoModel.cpp
usb-pd
USBPD.cpp
Utils.cpp
)
add_library(drivers ${sources})
target_link_libraries(drivers PRIVATE BSP BSPImplementation mainSource languages PUBLIC USBPDLib FreeRTOS)
target_include_directories(drivers PUBLIC .)
add_subdirectory(usb-pd)

View File

@@ -9,7 +9,7 @@
#ifndef FONT_H_
#define FONT_H_
#include "Translation.h"
#include <stdint.h>
#define FONT_12_WIDTH 12
// THE MAIN FONTS ARE NO LONGER HERE, MOVED TO PYTHON AUTO GEN

View File

@@ -631,3 +631,36 @@ void OLED::drawHeatSymbol(uint8_t state) {
}
bool OLED::isInitDone() { return initDone; }
bool OLED::getRotation() {
#ifdef OLED_FLIP
return !inLeftHandedMode;
#else
return inLeftHandedMode;
#endif
}
void OLED::setCursor(int16_t x, int16_t y) {
cursor_x = x;
cursor_y = y;
}
void OLED::refresh() {
I2C_CLASS::Transmit(DEVICEADDR_OLED, screenBuffer, FRAMEBUFFER_START + (OLED_WIDTH * 2));
// DMA tx time is ~ 20mS Ensure after calling this you delay for at least 25ms
// or we need to goto double buffering
}
void OLED::setDisplayState(OLED::DisplayState state) {
displayState = state;
screenBuffer[1] = (state == ON) ? 0xAF : 0xAE;
}
// Clears the buffer
void OLED::clearScreen() { memset(firstStripPtr, 0, OLED_WIDTH * 2); }
// Draws the battery level symbol
void OLED::drawBattery(uint8_t state) { drawSymbol(3 + (state > 10 ? 10 : state)); }
// Draws a checkbox
void OLED::drawCheckbox(bool state) { drawSymbol((state) ? 16 : 17); }
void OLED::drawImage(const uint8_t *buffer, uint8_t x, uint8_t width) { drawArea(x, 0, width, 16, buffer); }
int16_t OLED::getCursorX() { return cursor_x; }

View File

@@ -14,13 +14,6 @@
#include <BSP.h>
#include <stdbool.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "FreeRTOS.h"
#ifdef __cplusplus
}
#endif
#ifdef OLED_I2CBB
#include "I2CBB.hpp"
@@ -48,46 +41,30 @@ public:
static void initialize(); // Startup the I2C coms (brings screen out of reset etc)
static bool isInitDone();
// Draw the buffer out to the LCD using the DMA Channel
static void refresh() {
I2C_CLASS::Transmit(DEVICEADDR_OLED, screenBuffer, FRAMEBUFFER_START + (OLED_WIDTH * 2));
// DMA tx time is ~ 20mS Ensure after calling this you delay for at least 25ms
// or we need to goto double buffering
}
static void refresh();
static void setDisplayState(DisplayState state) {
displayState = state;
screenBuffer[1] = (state == ON) ? 0xAF : 0xAE;
}
static void setDisplayState(DisplayState state);
static void setRotation(bool leftHanded); // Set the rotation for the screen
// Get the current rotation of the LCD
static bool getRotation() {
#ifdef OLED_FLIP
return !inLeftHandedMode;
#else
return inLeftHandedMode;
#endif
}
static bool getRotation();
static void setBrightness(uint8_t contrast);
static void setInverseDisplay(bool inverted);
static int16_t getCursorX() { return cursor_x; }
static int16_t getCursorX();
static void print(const char *string, FontStyle fontStyle); // Draw a string to the current location, with selected font
static void printWholeScreen(const char *string);
// Set the cursor location by pixels
static void setCursor(int16_t x, int16_t y) {
cursor_x = x;
cursor_y = y;
}
static void setCursor(int16_t x, int16_t y);
// Draws an image to the buffer, at x offset from top to bottom (fixed height renders)
static void drawImage(const uint8_t *buffer, uint8_t x, uint8_t width) { drawArea(x, 0, width, 16, buffer); }
static void drawImage(const uint8_t *buffer, uint8_t x, uint8_t width);
// Draws a number at the current cursor location
static void printNumber(uint16_t number, uint8_t places, FontStyle fontStyle, bool noLeaderZeros = true);
// Clears the buffer
static void clearScreen() { memset(firstStripPtr, 0, OLED_WIDTH * 2); }
static void clearScreen();
// Draws the battery level symbol
static void drawBattery(uint8_t state) { drawSymbol(3 + (state > 10 ? 10 : state)); }
static void drawBattery(uint8_t state);
// Draws a checkbox
static void drawCheckbox(bool state) { drawSymbol((state) ? 16 : 17); }
static void drawCheckbox(bool state);
static void debugNumber(int32_t val, FontStyle fontStyle);
static void drawHex(uint32_t x, FontStyle fontStyle);
static void drawSymbol(uint8_t symbolID); // Used for drawing symbols of a predictable width

View File

@@ -1,4 +1,5 @@
#include "USBPD.h"
#include "Settings.h"
#include "configuration.h"
#if POW_PD

View File

@@ -0,0 +1,25 @@
if (LANG STREQUAL "")
message(FATAL_ERROR "You must specify a language")
endif()
add_custom_command(
OUTPUT "translation_${LANG}.cpp"
COMMAND
python3 ${CMAKE_CURRENT_SOURCE_DIR}/../../../Translations/make_translation.py -o translation_${LANG}.cpp ${LANG}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../../../Translations/translation_${LANG}.json
VERBATIM)
set(sources
translation_${LANG}.cpp
# lang_multi.cpp
lang_single.cpp
)
add_library(languages ${sources})
target_link_libraries(languages PRIVATE drivers brieflz mainSource )

View File

@@ -0,0 +1,17 @@
set(sources
freertos.c
FreeRTOSHooks.c
settingsGUI.cpp
main.cpp
power.cpp
QC3.cpp
ScrollMessage.cpp
Settings.cpp
syscalls.c
Translation.cpp
)
add_library(mainSource ${sources})
target_include_directories(mainSource PUBLIC .)
target_link_libraries(mainSource PRIVATE brieflz BSP FreeRTOS drivers languages)

View File

@@ -8,14 +8,8 @@
#ifndef INC_QC3_H_
#define INC_QC3_H_
#include "stdint.h"
#ifdef __cplusplus
extern "C" {
#endif
void seekQC(int16_t Vx10, uint16_t divisor);
void startQC(uint16_t divisor); // Tries to negotiate QC for highest voltage, must be run after
bool hasQCNegotiated(); // Returns true if a QC negotiation worked (we are using QC)
#ifdef __cplusplus
}
#endif
#endif /* INC_QC3_H_ */

View File

@@ -1,6 +1,6 @@
#include "ScrollMessage.hpp"
#include "OLED.hpp"
#include "Settings.h"
#include "configuration.h"
/**

View File

@@ -0,0 +1,14 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(sources
GUIThread.cpp
MOVThread.cpp
PIDThread.cpp
POWThread.cpp
shared.cpp
)
add_library(threads ${sources})
target_include_directories(threads PUBLIC .)
target_link_libraries(threads PRIVATE mainSource drivers BSP FreeRTOS languages BSPImplementation )

View File

@@ -0,0 +1,4 @@
#include "FreeRTOS.h"
#include "main.hpp"
#include "task.h"
TaskHandle_t pidTaskNotification = NULL;

View File

@@ -0,0 +1,10 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(sources
brieflz.c
depack.c
)
add_library(brieflz ${sources})
target_include_directories(brieflz PUBLIC .)

View File

@@ -52,7 +52,7 @@ MINIWARE_INC_CMSIS_DEVICE = ./Core/BSP/Miniware/Vendor/CMSIS/Device/ST/STM32F1xx
MINIWARE_CMSIS_CORE_INC_DIR = ./Core/BSP/Miniware/Vendor/CMSIS/Include
MINIWARE_HAL_INC_DIR = ./Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc
MINIWARE_HAL_LEGACY_INC_DIR = ./Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/Legacy
MINIWARE_STARTUP_DIR = ./Startup
MINIWARE_STARTUP_DIR = ./Core/BSP/Miniware
MINIWARE_INC_DIR = ./Core/BSP/Miniware
MINIWARE_LD_FILE = ./Core/BSP/Miniware/stm32f103.ld
@@ -60,7 +60,7 @@ MHP30_INC_CMSIS_DEVICE = ./Core/BSP/MHP30/Vendor/CMSIS/Device/ST/STM32F1xx/Inclu
MHP30_CMSIS_CORE_INC_DIR = ./Core/BSP/MHP30/Vendor/CMSIS/Include
MHP30_HAL_INC_DIR = ./Core/BSP/MHP30/Vendor/STM32F1xx_HAL_Driver/Inc
MHP30_HAL_LEGACY_INC_DIR = ./Core/BSP/MHP30/Vendor/STM32F1xx_HAL_Driver/Inc/Legacy
MHP30_STARTUP_DIR = ./Startup
MHP30_STARTUP_DIR = ./Core/BSP/MHP30
MHP30_INC_DIR = ./Core/BSP/MHP30
MHP30_LD_FILE = ./Core/BSP/MHP30/stm32f103.ld
@@ -71,8 +71,8 @@ PINE_NMSIS_INC_DIR = ./Core/BSP/Pine64/Vendor/NMSIS/Core/Include
PINE_FREERTOS_PORT_INC_DIR = ./Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC
SOURCE_MIDDLEWARES_DIR = ./Middlewares
FRTOS_CMIS_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS
FRTOS_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/include
FRTOS_CMIS_INC_DIR = ./Middlewares/FreeRTOS/Source/CMSIS_RTOS
FRTOS_INC_DIR = ./Middlewares/FreeRTOS/Source/include
DRIVER_INC_DIR =./Core/Drivers
BSP_INC_DIR = ./Core/BSP
THREADS_INC_DIR = ./Core/Threads

View File

@@ -0,0 +1 @@
add_subdirectory(FreeRTOS)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
set(sources
croutine.c
event_groups.c
list.c
queue.c
tasks.c
timers.c
CMSIS_RTOS/cmsis_os.c
)
add_library(FreeRTOS ${sources})
#Reqired to be able to grab the freertos config header
target_link_libraries(FreeRTOS PRIVATE BSP PUBLIC BSPImplementation)
target_include_directories(FreeRTOS PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_RTOS)

File diff suppressed because it is too large Load Diff