From e6a080c33d69203d9ebe2560283488e732efbcaa Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Mon, 28 Mar 2022 19:29:13 +1100 Subject: [PATCH] CMake --- .gitignore | 4 +- Dockerfile | 2 +- source/CMake/arm-gcc.cmake | 9 + source/CMake/gd32vf1.cmake | 7 + source/CMake/riscv-gcc.cmake | 9 + source/CMake/shared-compiler-settings.cmake | 26 + source/CMake/stm32f1.cmake | 6 + source/CMakeLists.txt | 89 + source/Core/BSP/CMakeLists.txt | 20 + .../BSP/MHP30}/startup_stm32f103t8ux.S | 0 source/Core/BSP/Miniware/CMakeLists.txt | 52 + .../{ST/STM32F1xx/Include => }/stm32f103xb.h | 0 .../{ST/STM32F1xx/Include => }/stm32f1xx.h | 0 .../STM32F1xx/Include => }/system_stm32f1xx.h | 0 .../Core/BSP/Miniware/startup_stm32f103t8ux.S | 344 +++ source/Core/BSP/Pine64/CMakeLists.txt | 75 + source/Core/BSP/Pine64/FreeRTOSConfig.h | 4 +- source/Core/BSP/Pine64/IRQ.cpp | 1 + ...freertos_risc_v_chip_specific_extensions.h | 19 + .../OS/FreeRTOS/Source/portable/GCC/port.c | 680 +----- .../OS/FreeRTOS/Source/portable/GCC/portasm.S | 752 +++---- .../FreeRTOS/Source/portable/GCC/portmacro.h | 154 +- .../Board/pinecil/openocd_gd32vf103.cfg | 48 - source/Core/CMakeLists.txt | 6 + source/Core/Drivers/CMakeLists.txt | 25 + source/Core/Drivers/usb-pd | 2 +- source/Core/LangSupport/CMakeLists.txt | 22 + source/Core/Src/CMakeLists.txt | 17 + source/Core/{Inc => Src}/FreeRTOSHooks.h | 0 source/Core/{Inc => Src}/QC3.h | 0 source/Core/{Inc => Src}/ScrollMessage.hpp | 0 source/Core/{Inc => Src}/Settings.h | 0 source/Core/{Inc => Src}/Translation.h | 0 source/Core/{Inc => Src}/Translation_multi.h | 0 source/Core/{Inc => Src}/expMovingAverage.h | 0 .../Core/{Inc/settingsGUI.hpp => Src/gui.hpp} | 0 source/Core/{Inc => Src}/history.hpp | 0 source/Core/{Inc => Src}/main.hpp | 0 source/Core/{Inc => Src}/power.hpp | 0 source/Core/Src/settingsGUI.hpp | 40 + source/Core/{Inc => Src}/stm32f1xx_hal_conf.h | 0 source/Core/{Inc => Src}/stm32f1xx_it.h | 0 source/Core/Threads/CMakeLists.txt | 14 + source/Core/Threads/shared.cpp | 4 + source/Core/brieflz/CMakeLists.txt | 10 + source/Makefile | 8 +- source/Middlewares/CMakeLists.txt | 1 + .../FreeRTOS/CMSIS_RTOS/cmsis_os.c | 1608 ++++++++++++++ .../Source => FreeRTOS}/CMSIS_RTOS/cmsis_os.h | 0 source/Middlewares/FreeRTOS/CMakeLists.txt | 17 + .../FreeRTOS/Source => FreeRTOS}/croutine.c | 0 .../Source => FreeRTOS}/event_groups.c | 0 .../Source => FreeRTOS}/include/FreeRTOS.h | 0 .../Source => FreeRTOS}/include/StackMacros.h | 0 .../Source => FreeRTOS}/include/atomic.h | 0 .../Source => FreeRTOS}/include/croutine.h | 0 .../include/event_groups.h | 0 .../Source => FreeRTOS}/include/list.h | 0 .../include/message_buffer.h | 0 .../include/mpu_prototypes.h | 0 .../include/mpu_wrappers.h | 0 .../Source => FreeRTOS}/include/portable.h | 0 .../Source => FreeRTOS}/include/projdefs.h | 0 .../Source => FreeRTOS}/include/queue.h | 0 .../Source => FreeRTOS}/include/semphr.h | 0 .../include/stack_macros.h | 0 .../include/stream_buffer.h | 0 .../Source => FreeRTOS}/include/task.h | 0 .../Source => FreeRTOS}/include/timers.h | 0 .../FreeRTOS/Source => FreeRTOS}/list.c | 0 .../FreeRTOS/Source => FreeRTOS}/queue.c | 0 .../FreeRTOS/Source => FreeRTOS}/tasks.c | 0 .../FreeRTOS/Source => FreeRTOS}/timers.c | 0 .../FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c | 1881 ----------------- .../gd32vf103.ld} | 0 .../BSP/Miniware => linkers}/stm32f103.ld | 0 76 files changed, 2997 insertions(+), 2959 deletions(-) create mode 100644 source/CMake/arm-gcc.cmake create mode 100644 source/CMake/gd32vf1.cmake create mode 100644 source/CMake/riscv-gcc.cmake create mode 100644 source/CMake/shared-compiler-settings.cmake create mode 100644 source/CMake/stm32f1.cmake create mode 100644 source/CMakeLists.txt create mode 100644 source/Core/BSP/CMakeLists.txt rename source/{Startup => Core/BSP/MHP30}/startup_stm32f103t8ux.S (100%) create mode 100644 source/Core/BSP/Miniware/CMakeLists.txt rename source/Core/BSP/Miniware/Vendor/CMSIS/Device/{ST/STM32F1xx/Include => }/stm32f103xb.h (100%) rename source/Core/BSP/Miniware/Vendor/CMSIS/Device/{ST/STM32F1xx/Include => }/stm32f1xx.h (100%) rename source/Core/BSP/Miniware/Vendor/CMSIS/Device/{ST/STM32F1xx/Include => }/system_stm32f1xx.h (100%) create mode 100644 source/Core/BSP/Miniware/startup_stm32f103t8ux.S create mode 100644 source/Core/BSP/Pine64/CMakeLists.txt create mode 100644 source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/freertos_risc_v_chip_specific_extensions.h delete mode 100644 source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Board/pinecil/openocd_gd32vf103.cfg create mode 100644 source/Core/CMakeLists.txt create mode 100644 source/Core/Drivers/CMakeLists.txt create mode 100644 source/Core/LangSupport/CMakeLists.txt create mode 100644 source/Core/Src/CMakeLists.txt rename source/Core/{Inc => Src}/FreeRTOSHooks.h (100%) rename source/Core/{Inc => Src}/QC3.h (100%) rename source/Core/{Inc => Src}/ScrollMessage.hpp (100%) rename source/Core/{Inc => Src}/Settings.h (100%) rename source/Core/{Inc => Src}/Translation.h (100%) rename source/Core/{Inc => Src}/Translation_multi.h (100%) rename source/Core/{Inc => Src}/expMovingAverage.h (100%) rename source/Core/{Inc/settingsGUI.hpp => Src/gui.hpp} (100%) rename source/Core/{Inc => Src}/history.hpp (100%) rename source/Core/{Inc => Src}/main.hpp (100%) rename source/Core/{Inc => Src}/power.hpp (100%) create mode 100644 source/Core/Src/settingsGUI.hpp rename source/Core/{Inc => Src}/stm32f1xx_hal_conf.h (100%) rename source/Core/{Inc => Src}/stm32f1xx_it.h (100%) create mode 100644 source/Core/Threads/CMakeLists.txt create mode 100644 source/Core/Threads/shared.cpp create mode 100644 source/Core/brieflz/CMakeLists.txt create mode 100644 source/Middlewares/CMakeLists.txt create mode 100644 source/Middlewares/FreeRTOS/CMSIS_RTOS/cmsis_os.c rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/CMSIS_RTOS/cmsis_os.h (100%) create mode 100644 source/Middlewares/FreeRTOS/CMakeLists.txt rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/croutine.c (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/event_groups.c (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/FreeRTOS.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/StackMacros.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/atomic.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/croutine.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/event_groups.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/list.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/message_buffer.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/mpu_prototypes.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/mpu_wrappers.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/portable.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/projdefs.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/queue.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/semphr.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/stack_macros.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/stream_buffer.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/task.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/include/timers.h (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/list.c (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/queue.c (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/tasks.c (100%) rename source/Middlewares/{Third_Party/FreeRTOS/Source => FreeRTOS}/timers.c (100%) delete mode 100644 source/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c rename source/{Core/BSP/Pine64/Vendor/SoC/gd32vf103/Board/pinecil/Source/GCC/gcc_gd32vf103_flashxip.ld => linkers/gd32vf103.ld} (100%) rename source/{Core/BSP/Miniware => linkers}/stm32f103.ld (100%) diff --git a/.gitignore b/.gitignore index a9a7c21a..7909b5ad 100644 --- a/.gitignore +++ b/.gitignore @@ -176,4 +176,6 @@ fabric.properties CoreCompileInputs.cache .vscode/settings.json -source/compile_commands.json +source/compile_commands.json +source/build/ +source/null.cpp diff --git a/Dockerfile b/Dockerfile index d420b12b..2449836a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 diff --git a/source/CMake/arm-gcc.cmake b/source/CMake/arm-gcc.cmake new file mode 100644 index 00000000..ce2b51af --- /dev/null +++ b/source/CMake/arm-gcc.cmake @@ -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") + + diff --git a/source/CMake/gd32vf1.cmake b/source/CMake/gd32vf1.cmake new file mode 100644 index 00000000..6b7945b1 --- /dev/null +++ b/source/CMake/gd32vf1.cmake @@ -0,0 +1,7 @@ +# core flags + +set(CORE_FLAGS "-march=rv32imac -mabi=ilp32 -mcmodel=medlow -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) +# target_link_libraries(${elf_file} PUBLIC -nostartfiles --specs=${CMAKE_CURRENT_SOURCE_DIR}/patch.specs) diff --git a/source/CMake/riscv-gcc.cmake b/source/CMake/riscv-gcc.cmake new file mode 100644 index 00000000..8addf072 --- /dev/null +++ b/source/CMake/riscv-gcc.cmake @@ -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") + + diff --git a/source/CMake/shared-compiler-settings.cmake b/source/CMake/shared-compiler-settings.cmake new file mode 100644 index 00000000..efb351bb --- /dev/null +++ b/source/CMake/shared-compiler-settings.cmake @@ -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) + diff --git a/source/CMake/stm32f1.cmake b/source/CMake/stm32f1.cmake new file mode 100644 index 00000000..9a5ba5af --- /dev/null +++ b/source/CMake/stm32f1.cmake @@ -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) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt new file mode 100644 index 00000000..141b7984 --- /dev/null +++ b/source/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.13) +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 + #VERSION 0.0.0.0 + 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} PUBLIC BSP mainSource threads FreeRTOS languages drivers BSPImplementation) + +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 +target_link_libraries(${elf_file} PUBLIC "-g -Wl,--gc-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}) diff --git a/source/Core/BSP/CMakeLists.txt b/source/Core/BSP/CMakeLists.txt new file mode 100644 index 00000000..b54db137 --- /dev/null +++ b/source/Core/BSP/CMakeLists.txt @@ -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 mainSource BSPImplementation) + +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() diff --git a/source/Startup/startup_stm32f103t8ux.S b/source/Core/BSP/MHP30/startup_stm32f103t8ux.S similarity index 100% rename from source/Startup/startup_stm32f103t8ux.S rename to source/Core/BSP/MHP30/startup_stm32f103t8ux.S diff --git a/source/Core/BSP/Miniware/CMakeLists.txt b/source/Core/BSP/Miniware/CMakeLists.txt new file mode 100644 index 00000000..650bd30a --- /dev/null +++ b/source/Core/BSP/Miniware/CMakeLists.txt @@ -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) \ No newline at end of file diff --git a/source/Core/BSP/Miniware/Vendor/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xb.h b/source/Core/BSP/Miniware/Vendor/CMSIS/Device/stm32f103xb.h similarity index 100% rename from source/Core/BSP/Miniware/Vendor/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xb.h rename to source/Core/BSP/Miniware/Vendor/CMSIS/Device/stm32f103xb.h diff --git a/source/Core/BSP/Miniware/Vendor/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h b/source/Core/BSP/Miniware/Vendor/CMSIS/Device/stm32f1xx.h similarity index 100% rename from source/Core/BSP/Miniware/Vendor/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h rename to source/Core/BSP/Miniware/Vendor/CMSIS/Device/stm32f1xx.h diff --git a/source/Core/BSP/Miniware/Vendor/CMSIS/Device/ST/STM32F1xx/Include/system_stm32f1xx.h b/source/Core/BSP/Miniware/Vendor/CMSIS/Device/system_stm32f1xx.h similarity index 100% rename from source/Core/BSP/Miniware/Vendor/CMSIS/Device/ST/STM32F1xx/Include/system_stm32f1xx.h rename to source/Core/BSP/Miniware/Vendor/CMSIS/Device/system_stm32f1xx.h diff --git a/source/Core/BSP/Miniware/startup_stm32f103t8ux.S b/source/Core/BSP/Miniware/startup_stm32f103t8ux.S new file mode 100644 index 00000000..f8d1c8ed --- /dev/null +++ b/source/Core/BSP/Miniware/startup_stm32f103t8ux.S @@ -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****/ diff --git a/source/Core/BSP/Pine64/CMakeLists.txt b/source/Core/BSP/Pine64/CMakeLists.txt new file mode 100644 index 00000000..119941bf --- /dev/null +++ b/source/Core/BSP/Pine64/CMakeLists.txt @@ -0,0 +1,75 @@ +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 + 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 + # 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 + + ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/ + ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/close.c + ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/fstat.c + ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/gettimeofday.c + ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/isatty.c + ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/lseek.c + ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/read.c + ${CMAKE_CURRENT_SOURCE_DIR}/Vendor/SoC/gd32vf103/Common/Source/Stubs/sbrk.c + +) + + +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 PUBLIC brieflz BSP mainSource drivers threads drivers) + + +# 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) \ No newline at end of file diff --git a/source/Core/BSP/Pine64/FreeRTOSConfig.h b/source/Core/BSP/Pine64/FreeRTOSConfig.h index 91a5e4b6..b6b01124 100644 --- a/source/Core/BSP/Pine64/FreeRTOSConfig.h +++ b/source/Core/BSP/Pine64/FreeRTOSConfig.h @@ -2,10 +2,12 @@ #define FREERTOS_CONFIG_H #include "nuclei_sdk_soc.h" #include +#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) diff --git a/source/Core/BSP/Pine64/IRQ.cpp b/source/Core/BSP/Pine64/IRQ.cpp index 6aa77aef..357e4d67 100644 --- a/source/Core/BSP/Pine64/IRQ.cpp +++ b/source/Core/BSP/Pine64/IRQ.cpp @@ -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; diff --git a/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/freertos_risc_v_chip_specific_extensions.h b/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/freertos_risc_v_chip_specific_extensions.h new file mode 100644 index 00000000..97ae23c1 --- /dev/null +++ b/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/freertos_risc_v_chip_specific_extensions.h @@ -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__ */ \ No newline at end of file diff --git a/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/port.c b/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/port.c index a20833aa..c8cd19bf 100644 --- a/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/port.c +++ b/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/port.c @@ -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 -//#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 */ diff --git a/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/portasm.S b/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/portasm.S index eb9fa194..0923450e 100644 --- a/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/portasm.S +++ b/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/portasm.S @@ -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 +/*-----------------------------------------------------------*/ \ No newline at end of file diff --git a/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/portmacro.h b/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/portmacro.h index b2911fcd..1f1ab337 100644 --- a/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/portmacro.h +++ b/source/Core/BSP/Pine64/Vendor/OS/FreeRTOS/Source/portable/GCC/portmacro.h @@ -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 diff --git a/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Board/pinecil/openocd_gd32vf103.cfg b/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Board/pinecil/openocd_gd32vf103.cfg deleted file mode 100644 index 733b4bd9..00000000 --- a/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Board/pinecil/openocd_gd32vf103.cfg +++ /dev/null @@ -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 diff --git a/source/Core/CMakeLists.txt b/source/Core/CMakeLists.txt new file mode 100644 index 00000000..63307023 --- /dev/null +++ b/source/Core/CMakeLists.txt @@ -0,0 +1,6 @@ +add_subdirectory(brieflz) +add_subdirectory(BSP) +add_subdirectory(Drivers) +add_subdirectory(LangSupport) +add_subdirectory(Src) +add_subdirectory(Threads) diff --git a/source/Core/Drivers/CMakeLists.txt b/source/Core/Drivers/CMakeLists.txt new file mode 100644 index 00000000..a257be80 --- /dev/null +++ b/source/Core/Drivers/CMakeLists.txt @@ -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 PUBLIC BSP USBPDLib) +target_include_directories(drivers PUBLIC .) + +add_subdirectory(usb-pd) \ No newline at end of file diff --git a/source/Core/Drivers/usb-pd b/source/Core/Drivers/usb-pd index b3859826..6dc1a77a 160000 --- a/source/Core/Drivers/usb-pd +++ b/source/Core/Drivers/usb-pd @@ -1 +1 @@ -Subproject commit b38598261df4f705bcbd37cdd5dcccfaa5ab7b4a +Subproject commit 6dc1a77a8c93c7a08d31ba1b09000e106b20f9b1 diff --git a/source/Core/LangSupport/CMakeLists.txt b/source/Core/LangSupport/CMakeLists.txt new file mode 100644 index 00000000..4a601c95 --- /dev/null +++ b/source/Core/LangSupport/CMakeLists.txt @@ -0,0 +1,22 @@ + + + +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 PUBLIC drivers brieflz ) + diff --git a/source/Core/Src/CMakeLists.txt b/source/Core/Src/CMakeLists.txt new file mode 100644 index 00000000..7b586551 --- /dev/null +++ b/source/Core/Src/CMakeLists.txt @@ -0,0 +1,17 @@ +set(sources +freertos.c +FreeRTOSHooks.c +gui.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 PUBLIC brieflz BSP FreeRTOS drivers languages) diff --git a/source/Core/Inc/FreeRTOSHooks.h b/source/Core/Src/FreeRTOSHooks.h similarity index 100% rename from source/Core/Inc/FreeRTOSHooks.h rename to source/Core/Src/FreeRTOSHooks.h diff --git a/source/Core/Inc/QC3.h b/source/Core/Src/QC3.h similarity index 100% rename from source/Core/Inc/QC3.h rename to source/Core/Src/QC3.h diff --git a/source/Core/Inc/ScrollMessage.hpp b/source/Core/Src/ScrollMessage.hpp similarity index 100% rename from source/Core/Inc/ScrollMessage.hpp rename to source/Core/Src/ScrollMessage.hpp diff --git a/source/Core/Inc/Settings.h b/source/Core/Src/Settings.h similarity index 100% rename from source/Core/Inc/Settings.h rename to source/Core/Src/Settings.h diff --git a/source/Core/Inc/Translation.h b/source/Core/Src/Translation.h similarity index 100% rename from source/Core/Inc/Translation.h rename to source/Core/Src/Translation.h diff --git a/source/Core/Inc/Translation_multi.h b/source/Core/Src/Translation_multi.h similarity index 100% rename from source/Core/Inc/Translation_multi.h rename to source/Core/Src/Translation_multi.h diff --git a/source/Core/Inc/expMovingAverage.h b/source/Core/Src/expMovingAverage.h similarity index 100% rename from source/Core/Inc/expMovingAverage.h rename to source/Core/Src/expMovingAverage.h diff --git a/source/Core/Inc/settingsGUI.hpp b/source/Core/Src/gui.hpp similarity index 100% rename from source/Core/Inc/settingsGUI.hpp rename to source/Core/Src/gui.hpp diff --git a/source/Core/Inc/history.hpp b/source/Core/Src/history.hpp similarity index 100% rename from source/Core/Inc/history.hpp rename to source/Core/Src/history.hpp diff --git a/source/Core/Inc/main.hpp b/source/Core/Src/main.hpp similarity index 100% rename from source/Core/Inc/main.hpp rename to source/Core/Src/main.hpp diff --git a/source/Core/Inc/power.hpp b/source/Core/Src/power.hpp similarity index 100% rename from source/Core/Inc/power.hpp rename to source/Core/Src/power.hpp diff --git a/source/Core/Src/settingsGUI.hpp b/source/Core/Src/settingsGUI.hpp new file mode 100644 index 00000000..9905973f --- /dev/null +++ b/source/Core/Src/settingsGUI.hpp @@ -0,0 +1,40 @@ +/* + * settingsGUI.h + * + * Created on: 3Sep.,2017 + * Author: Ben V. Brown + */ + +#ifndef GUI_HPP_ +#define GUI_HPP_ +#include "BSP.h" +#include "Settings.h" +#include "Translation.h" + +#define PRESS_ACCEL_STEP (TICKS_100MS / 3) +#define PRESS_ACCEL_INTERVAL_MIN TICKS_100MS +#define PRESS_ACCEL_INTERVAL_MAX (TICKS_100MS * 3) + +// GUI holds the menu structure and all its methods for the menu itself + +// Declarations for all the methods for the settings menu (at end of this file) + +// Struct for holding the function pointers and descriptions +typedef struct { + // The settings description index, please use the `SETTINGS_DESC` macro with + // the `SettingsItemIndex` enum. Use 0 for no description. + uint8_t description; + // return true if increment reached the maximum value + bool (*const incrementHandler)(void); + void (*const draw)(void); + bool (*const isVisible)(void); + // If this is set, we will automatically use the settings increment handler instead, set >= num settings to disable + SettingsOptions autoSettingOption; +} menuitem; + +void enterSettingsMenu(); +void GUIDelay(); +void warnUser(const char *warning, const int timeout); +extern const menuitem rootSettingsMenu[]; + +#endif /* GUI_HPP_ */ diff --git a/source/Core/Inc/stm32f1xx_hal_conf.h b/source/Core/Src/stm32f1xx_hal_conf.h similarity index 100% rename from source/Core/Inc/stm32f1xx_hal_conf.h rename to source/Core/Src/stm32f1xx_hal_conf.h diff --git a/source/Core/Inc/stm32f1xx_it.h b/source/Core/Src/stm32f1xx_it.h similarity index 100% rename from source/Core/Inc/stm32f1xx_it.h rename to source/Core/Src/stm32f1xx_it.h diff --git a/source/Core/Threads/CMakeLists.txt b/source/Core/Threads/CMakeLists.txt new file mode 100644 index 00000000..bb233e92 --- /dev/null +++ b/source/Core/Threads/CMakeLists.txt @@ -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 PUBLIC BSP FreeRTOS drivers languages) diff --git a/source/Core/Threads/shared.cpp b/source/Core/Threads/shared.cpp new file mode 100644 index 00000000..bed7410a --- /dev/null +++ b/source/Core/Threads/shared.cpp @@ -0,0 +1,4 @@ +#include "FreeRTOS.h" +#include "main.hpp" +#include "task.h" +TaskHandle_t pidTaskNotification = NULL; \ No newline at end of file diff --git a/source/Core/brieflz/CMakeLists.txt b/source/Core/brieflz/CMakeLists.txt new file mode 100644 index 00000000..5d3c72d8 --- /dev/null +++ b/source/Core/brieflz/CMakeLists.txt @@ -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 .) diff --git a/source/Makefile b/source/Makefile index 0d7a78a4..af41e381 100644 --- a/source/Makefile +++ b/source/Makefile @@ -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 diff --git a/source/Middlewares/CMakeLists.txt b/source/Middlewares/CMakeLists.txt new file mode 100644 index 00000000..3ba8ad79 --- /dev/null +++ b/source/Middlewares/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(FreeRTOS) diff --git a/source/Middlewares/FreeRTOS/CMSIS_RTOS/cmsis_os.c b/source/Middlewares/FreeRTOS/CMSIS_RTOS/cmsis_os.c new file mode 100644 index 00000000..685b7fc3 --- /dev/null +++ b/source/Middlewares/FreeRTOS/CMSIS_RTOS/cmsis_os.c @@ -0,0 +1,1608 @@ +/* ---------------------------------------------------------------------- + * $Date: 5. February 2013 + * $Revision: V1.02 + * + * Project: CMSIS-RTOS API + * Title: cmsis_os.c + * + * Version 0.02 + * Initial Proposal Phase + * Version 0.03 + * osKernelStart added, optional feature: main started as thread + * osSemaphores have standard behavior + * osTimerCreate does not start the timer, added osTimerStart + * osThreadPass is renamed to osThreadYield + * Version 1.01 + * Support for C++ interface + * - const attribute removed from the osXxxxDef_t typedef's + * - const attribute added to the osXxxxDef macros + * Added: osTimerDelete, osMutexDelete, osSemaphoreDelete + * Added: osKernelInitialize + * Version 1.02 + * Control functions for short timeouts in microsecond resolution: + * Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec + * Removed: osSignalGet + * + * + *---------------------------------------------------------------------------- + * + * Portions Copyright � 2016 STMicroelectronics International N.V. All rights reserved. + * Portions Copyright (c) 2013 ARM LIMITED + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *---------------------------------------------------------------------------*/ + +/** + ****************************************************************************** + * @file cmsis_os.c + * @author MCD Application Team + * @date 03-March-2017 + * @brief CMSIS-RTOS API implementation for FreeRTOS V9.0.0 + ****************************************************************************** + * @attention + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +#include "cmsis_os.h" +#include "portmacro.h" +#include + +/* + * ARM Compiler 4/5 + */ +#if defined(__CC_ARM) + +#define __ASM __asm +#define __INLINE __inline +#define __STATIC_INLINE static __inline +#include "cmsis_armcc.h" + +/* + * GNU Compiler + */ +#elif defined(__GNUC__) + +#define __ASM __asm /*!< asm keyword for GNU Compiler */ +#define __INLINE inline /*!< inline keyword for GNU Compiler */ +#define __STATIC_INLINE static inline +uint32_t __get_IPSR(void); +// #include "cmsis_gcc.h" + +/* + * IAR Compiler + */ +#elif defined(__ICCARM__) + +#ifndef __ASM +#define __ASM __asm +#endif +#ifndef __INLINE +#define __INLINE inline +#endif +#ifndef __STATIC_INLINE +#define __STATIC_INLINE static inline +#endif + +#include +#endif + +extern void xPortSysTickHandler(void); + +/* Convert from CMSIS type osPriority to FreeRTOS priority number */ +static portBASE_TYPE makeFreeRtosPriority(osPriority priority) { + portBASE_TYPE fpriority = tskIDLE_PRIORITY; + + if (priority != osPriorityError) { + fpriority += (priority - osPriorityIdle); + } + + return fpriority; +} + +#if (INCLUDE_uxTaskPriorityGet == 1) +/* Convert from FreeRTOS priority number to CMSIS type osPriority */ +static osPriority makeCmsisPriority(portBASE_TYPE fpriority) { + osPriority priority = osPriorityError; + + if ((fpriority - tskIDLE_PRIORITY) <= (osPriorityRealtime - osPriorityIdle)) { + priority = (osPriority)((int)osPriorityIdle + (int)(fpriority - tskIDLE_PRIORITY)); + } + + return priority; +} +#endif + +/* Determine whether we are in thread mode or handler mode. */ +static int inHandlerMode(void) { return __get_IPSR() != 0; } + +/*********************** Kernel Control Functions *****************************/ +/** + * @brief Initialize the RTOS Kernel for creating objects. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS. + */ +osStatus osKernelInitialize(void); + +/** + * @brief Start the RTOS Kernel with executing the specified thread. + * @param thread_def thread definition referenced with \ref osThread. + * @param argument pointer that is passed to the thread function as start argument. + * @retval status code that indicates the execution status of the function + * @note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS. + */ +osStatus osKernelStart(void) { + vTaskStartScheduler(); + + return osOK; +} + +/** + * @brief Check if the RTOS kernel is already started + * @param None + * @retval (0) RTOS is not started + * (1) RTOS is started + * (-1) if this feature is disabled in FreeRTOSConfig.h + * @note MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every CMSIS-RTOS. + */ +int32_t osKernelRunning(void) { +#if ((INCLUDE_xTaskGetSchedulerState == 1) || (configUSE_TIMERS == 1)) + if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) + return 0; + else + return 1; +#else + return (-1); +#endif +} + +#if (defined(osFeature_SysTick) && (osFeature_SysTick != 0)) // System Timer available +/** + * @brief Get the value of the Kernel SysTick timer + * @param None + * @retval None + * @note MUST REMAIN UNCHANGED: \b osKernelSysTick shall be consistent in every CMSIS-RTOS. + */ +uint32_t osKernelSysTick(void) { + if (inHandlerMode()) { + return xTaskGetTickCountFromISR(); + } else { + return xTaskGetTickCount(); + } +} +#endif // System Timer available +/*********************** Thread Management *****************************/ +/** + * @brief Create a thread and add it to Active Threads and set it to state READY. + * @param thread_def thread definition referenced with \ref osThread. + * @param argument pointer that is passed to the thread function as start argument. + * @retval thread ID for reference by other functions or NULL in case of error. + * @note MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS. + */ +osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument) { + TaskHandle_t handle; + +#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) + if ((thread_def->buffer != NULL) && (thread_def->controlblock != NULL)) { + handle = xTaskCreateStatic((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), + thread_def->buffer, thread_def->controlblock); + } else { + if (xTaskCreate((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), &handle) != pdPASS) { + return NULL; + } + } +#elif (configSUPPORT_STATIC_ALLOCATION == 1) + + handle = xTaskCreateStatic((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), thread_def->buffer, + thread_def->controlblock); +#else + if (xTaskCreate((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), &handle) != pdPASS) { + return NULL; + } +#endif + + return handle; +} + +/** + * @brief Return the thread ID of the current running thread. + * @retval thread ID for reference by other functions or NULL in case of error. + * @note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS. + */ +osThreadId osThreadGetId(void) { +#if ((INCLUDE_xTaskGetCurrentTaskHandle == 1) || (configUSE_MUTEXES == 1)) + return xTaskGetCurrentTaskHandle(); +#else + return NULL; +#endif +} + +/** + * @brief Terminate execution of a thread and remove it from Active Threads. + * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be consistent in every CMSIS-RTOS. + */ +osStatus osThreadTerminate(osThreadId thread_id) { +#if (INCLUDE_vTaskDelete == 1) + vTaskDelete(thread_id); + return osOK; +#else + return osErrorOS; +#endif +} + +/** + * @brief Pass control to next thread that is in state \b READY. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS. + */ +osStatus osThreadYield(void) { + taskYIELD(); + + return osOK; +} + +/** + * @brief Change priority of an active thread. + * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. + * @param priority new priority value for the thread function. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS. + */ +osStatus osThreadSetPriority(osThreadId thread_id, osPriority priority) { +#if (INCLUDE_vTaskPrioritySet == 1) + vTaskPrioritySet(thread_id, makeFreeRtosPriority(priority)); + return osOK; +#else + return osErrorOS; +#endif +} + +/** + * @brief Get current priority of an active thread. + * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. + * @retval current priority value of the thread function. + * @note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS. + */ +osPriority osThreadGetPriority(osThreadId thread_id) { +#if (INCLUDE_uxTaskPriorityGet == 1) + if (inHandlerMode()) { + return makeCmsisPriority(uxTaskPriorityGetFromISR(thread_id)); + } else { + return makeCmsisPriority(uxTaskPriorityGet(thread_id)); + } +#else + return osPriorityError; +#endif +} + +/*********************** Generic Wait Functions *******************************/ +/** + * @brief Wait for Timeout (Time Delay) + * @param millisec time delay value + * @retval status code that indicates the execution status of the function. + */ +osStatus osDelay(uint32_t millisec) { +#if INCLUDE_vTaskDelay + TickType_t ticks = millisec / portTICK_PERIOD_MS; + + vTaskDelay(ticks ? ticks : 1); /* Minimum delay = 1 tick */ + + return osOK; +#else + (void)millisec; + + return osErrorResource; +#endif +} + +#if (defined(osFeature_Wait) && (osFeature_Wait != 0)) /* Generic Wait available */ +/** + * @brief Wait for Signal, Message, Mail, or Timeout + * @param millisec timeout value or 0 in case of no time-out + * @retval event that contains signal, message, or mail information or error code. + * @note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS. + */ +osEvent osWait(uint32_t millisec); + +#endif /* Generic Wait available */ + +/*********************** Timer Management Functions ***************************/ +/** + * @brief Create a timer. + * @param timer_def timer object referenced with \ref osTimer. + * @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior. + * @param argument argument to the timer call back function. + * @retval timer ID for reference by other functions or NULL in case of error. + * @note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS. + */ +osTimerId osTimerCreate(const osTimerDef_t *timer_def, os_timer_type type, void *argument) { +#if (configUSE_TIMERS == 1) + +#if ((configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1)) + if (timer_def->controlblock != NULL) { + return xTimerCreateStatic((const char *)"", + 1, // period should be filled when starting the Timer using osTimerStart + (type == osTimerPeriodic) ? pdTRUE : pdFALSE, (void *)argument, (TaskFunction_t)timer_def->ptimer, (StaticTimer_t *)timer_def->controlblock); + } else { + return xTimerCreate((const char *)"", + 1, // period should be filled when starting the Timer using osTimerStart + (type == osTimerPeriodic) ? pdTRUE : pdFALSE, (void *)argument, (TaskFunction_t)timer_def->ptimer); + } +#elif (configSUPPORT_STATIC_ALLOCATION == 1) + return xTimerCreateStatic((const char *)"", + 1, // period should be filled when starting the Timer using osTimerStart + (type == osTimerPeriodic) ? pdTRUE : pdFALSE, (void *)argument, (TaskFunction_t)timer_def->ptimer, (StaticTimer_t *)timer_def->controlblock); +#else + return xTimerCreate((const char *)"", + 1, // period should be filled when starting the Timer using osTimerStart + (type == osTimerPeriodic) ? pdTRUE : pdFALSE, (void *)argument, (TaskFunction_t)timer_def->ptimer); +#endif + +#else + return NULL; +#endif +} + +/** + * @brief Start or restart a timer. + * @param timer_id timer ID obtained by \ref osTimerCreate. + * @param millisec time delay value of the timer. + * @retval status code that indicates the execution status of the function + * @note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS. + */ +osStatus osTimerStart(osTimerId timer_id, uint32_t millisec) { + osStatus result = osOK; +#if (configUSE_TIMERS == 1) + portBASE_TYPE taskWoken = pdFALSE; + TickType_t ticks = millisec / portTICK_PERIOD_MS; + + if (ticks == 0) + ticks = 1; + + if (inHandlerMode()) { + if (xTimerChangePeriodFromISR(timer_id, ticks, &taskWoken) != pdPASS) { + result = osErrorOS; + } else { + portEND_SWITCHING_ISR(taskWoken); + } + } else { + if (xTimerChangePeriod(timer_id, ticks, 0) != pdPASS) + result = osErrorOS; + } + +#else + result = osErrorOS; +#endif + return result; +} + +/** + * @brief Stop a timer. + * @param timer_id timer ID obtained by \ref osTimerCreate + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS. + */ +osStatus osTimerStop(osTimerId timer_id) { + osStatus result = osOK; +#if (configUSE_TIMERS == 1) + portBASE_TYPE taskWoken = pdFALSE; + + if (inHandlerMode()) { + if (xTimerStopFromISR(timer_id, &taskWoken) != pdPASS) { + return osErrorOS; + } + portEND_SWITCHING_ISR(taskWoken); + } else { + if (xTimerStop(timer_id, 0) != pdPASS) { + result = osErrorOS; + } + } +#else + result = osErrorOS; +#endif + return result; +} + +/** + * @brief Delete a timer. + * @param timer_id timer ID obtained by \ref osTimerCreate + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS. + */ +osStatus osTimerDelete(osTimerId timer_id) { + osStatus result = osOK; + +#if (configUSE_TIMERS == 1) + + if (inHandlerMode()) { + return osErrorISR; + } else { + if ((xTimerDelete(timer_id, osWaitForever)) != pdPASS) { + result = osErrorOS; + } + } + +#else + result = osErrorOS; +#endif + + return result; +} + +/*************************** Signal Management ********************************/ +/** + * @brief Set the specified Signal Flags of an active thread. + * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. + * @param signals specifies the signal flags of the thread that should be set. + * @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. + * @note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS. + */ +int32_t osSignalSet(osThreadId thread_id, int32_t signal) { +#if (configUSE_TASK_NOTIFICATIONS == 1) + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + uint32_t ulPreviousNotificationValue = 0; + + if (inHandlerMode()) { + if (xTaskGenericNotifyFromISR(thread_id, (uint32_t)signal, eSetBits, &ulPreviousNotificationValue, &xHigherPriorityTaskWoken) != pdPASS) + return 0x80000000; + + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } else if (xTaskGenericNotify(thread_id, (uint32_t)signal, eSetBits, &ulPreviousNotificationValue) != pdPASS) + return 0x80000000; + + return ulPreviousNotificationValue; +#else + (void)thread_id; + (void)signal; + + return 0x80000000; /* Task Notification not supported */ +#endif +} + +/** + * @brief Clear the specified Signal Flags of an active thread. + * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. + * @param signals specifies the signal flags of the thread that shall be cleared. + * @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. + * @note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS. + */ +int32_t osSignalClear(osThreadId thread_id, int32_t signal); + +/** + * @brief Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread. + * @param signals wait until all specified signal flags set or 0 for any single signal flag. + * @param millisec timeout value or 0 in case of no time-out. + * @retval event flag information or error code. + * @note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS. + */ +osEvent osSignalWait(int32_t signals, uint32_t millisec) { + osEvent ret; + +#if (configUSE_TASK_NOTIFICATIONS == 1) + + TickType_t ticks; + + ret.value.signals = 0; + ticks = 0; + if (millisec == osWaitForever) { + ticks = portMAX_DELAY; + } else if (millisec != 0) { + ticks = millisec / portTICK_PERIOD_MS; + if (ticks == 0) { + ticks = 1; + } + } + + if (inHandlerMode()) { + ret.status = osErrorISR; /*Not allowed in ISR*/ + } else { + if (xTaskNotifyWait(0, (uint32_t)signals, (uint32_t *)&ret.value.signals, ticks) != pdTRUE) { + if (ticks == 0) + ret.status = osOK; + else + ret.status = osEventTimeout; + } else if (ret.value.signals < 0) { + ret.status = osErrorValue; + } else + ret.status = osEventSignal; + } +#else + (void)signals; + (void)millisec; + + ret.status = osErrorOS; /* Task Notification not supported */ +#endif + + return ret; +} + +/**************************** Mutex Management ********************************/ +/** + * @brief Create and Initialize a Mutex object + * @param mutex_def mutex definition referenced with \ref osMutex. + * @retval mutex ID for reference by other functions or NULL in case of error. + * @note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS. + */ +osMutexId osMutexCreate(const osMutexDef_t *mutex_def) { +#if (configUSE_MUTEXES == 1) + +#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) + + if (mutex_def->controlblock != NULL) { + return xSemaphoreCreateMutexStatic(mutex_def->controlblock); + } else { + return xSemaphoreCreateMutex(); + } +#elif (configSUPPORT_STATIC_ALLOCATION == 1) + return xSemaphoreCreateMutexStatic(mutex_def->controlblock); +#else + return xSemaphoreCreateMutex(); +#endif +#else + return NULL; +#endif +} + +/** + * @brief Wait until a Mutex becomes available + * @param mutex_id mutex ID obtained by \ref osMutexCreate. + * @param millisec timeout value or 0 in case of no time-out. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS. + */ +osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec) { + TickType_t ticks; + portBASE_TYPE taskWoken = pdFALSE; + + if (mutex_id == NULL) { + return osErrorParameter; + } + + ticks = 0; + if (millisec == osWaitForever) { + ticks = portMAX_DELAY; + } else if (millisec != 0) { + ticks = millisec / portTICK_PERIOD_MS; + if (ticks == 0) { + ticks = 1; + } + } + + if (inHandlerMode()) { + if (xSemaphoreTakeFromISR(mutex_id, &taskWoken) != pdTRUE) { + return osErrorOS; + } + portEND_SWITCHING_ISR(taskWoken); + } else if (xSemaphoreTake(mutex_id, ticks) != pdTRUE) { + return osErrorOS; + } + + return osOK; +} + +/** + * @brief Release a Mutex that was obtained by \ref osMutexWait + * @param mutex_id mutex ID obtained by \ref osMutexCreate. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS. + */ +osStatus osMutexRelease(osMutexId mutex_id) { + osStatus result = osOK; + portBASE_TYPE taskWoken = pdFALSE; + + if (inHandlerMode()) { + if (xSemaphoreGiveFromISR(mutex_id, &taskWoken) != pdTRUE) { + return osErrorOS; + } + portEND_SWITCHING_ISR(taskWoken); + } else if (xSemaphoreGive(mutex_id) != pdTRUE) { + result = osErrorOS; + } + return result; +} + +/** + * @brief Delete a Mutex + * @param mutex_id mutex ID obtained by \ref osMutexCreate. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS. + */ +osStatus osMutexDelete(osMutexId mutex_id) { + if (inHandlerMode()) { + return osErrorISR; + } + + vQueueDelete(mutex_id); + + return osOK; +} + +/******************** Semaphore Management Functions **************************/ + +#if (defined(osFeature_Semaphore) && (osFeature_Semaphore != 0)) + +/** + * @brief Create and Initialize a Semaphore object used for managing resources + * @param semaphore_def semaphore definition referenced with \ref osSemaphore. + * @param count number of available resources. + * @retval semaphore ID for reference by other functions or NULL in case of error. + * @note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS. + */ +osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, int32_t count) { +#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) + + osSemaphoreId sema; + + if (semaphore_def->controlblock != NULL) { + if (count == 1) { + return xSemaphoreCreateBinaryStatic(semaphore_def->controlblock); + } else { +#if (configUSE_COUNTING_SEMAPHORES == 1) + return xSemaphoreCreateCountingStatic(count, count, semaphore_def->controlblock); +#else + return NULL; +#endif + } + } else { + if (count == 1) { + vSemaphoreCreateBinary(sema); + return sema; + } else { +#if (configUSE_COUNTING_SEMAPHORES == 1) + return xSemaphoreCreateCounting(count, count); +#else + return NULL; +#endif + } + } +#elif (configSUPPORT_STATIC_ALLOCATION == 1) // configSUPPORT_DYNAMIC_ALLOCATION == 0 + if (count == 1) { + return xSemaphoreCreateBinaryStatic(semaphore_def->controlblock); + } else { +#if (configUSE_COUNTING_SEMAPHORES == 1) + return xSemaphoreCreateCountingStatic(count, count, semaphore_def->controlblock); +#else + return NULL; +#endif + } +#else // configSUPPORT_STATIC_ALLOCATION == 0 && configSUPPORT_DYNAMIC_ALLOCATION == 1 + osSemaphoreId sema; + + if (count == 1) { + vSemaphoreCreateBinary(sema); + return sema; + } else { +#if (configUSE_COUNTING_SEMAPHORES == 1) + return xSemaphoreCreateCounting(count, count); +#else + return NULL; +#endif + } +#endif +} + +/** + * @brief Wait until a Semaphore token becomes available + * @param semaphore_id semaphore object referenced with \ref osSemaphore. + * @param millisec timeout value or 0 in case of no time-out. + * @retval number of available tokens, or -1 in case of incorrect parameters. + * @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS. + */ +int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec) { + TickType_t ticks; + portBASE_TYPE taskWoken = pdFALSE; + + if (semaphore_id == NULL) { + return osErrorParameter; + } + + ticks = 0; + if (millisec == osWaitForever) { + ticks = portMAX_DELAY; + } else if (millisec != 0) { + ticks = millisec / portTICK_PERIOD_MS; + if (ticks == 0) { + ticks = 1; + } + } + + if (inHandlerMode()) { + if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) { + return osErrorOS; + } + portEND_SWITCHING_ISR(taskWoken); + } else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) { + return osErrorOS; + } + + return osOK; +} + +/** + * @brief Release a Semaphore token + * @param semaphore_id semaphore object referenced with \ref osSemaphore. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS. + */ +osStatus osSemaphoreRelease(osSemaphoreId semaphore_id) { + osStatus result = osOK; + portBASE_TYPE taskWoken = pdFALSE; + + if (inHandlerMode()) { + if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) { + return osErrorOS; + } + portEND_SWITCHING_ISR(taskWoken); + } else { + if (xSemaphoreGive(semaphore_id) != pdTRUE) { + result = osErrorOS; + } + } + + return result; +} + +/** + * @brief Delete a Semaphore + * @param semaphore_id semaphore object referenced with \ref osSemaphore. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS. + */ +osStatus osSemaphoreDelete(osSemaphoreId semaphore_id) { + if (inHandlerMode()) { + return osErrorISR; + } + + vSemaphoreDelete(semaphore_id); + + return osOK; +} + +#endif /* Use Semaphores */ + +/******************* Memory Pool Management Functions ***********************/ + +#if (defined(osFeature_Pool) && (osFeature_Pool != 0)) + +// TODO +// This is a primitive and inefficient wrapper around the existing FreeRTOS memory management. +// A better implementation will have to modify heap_x.c! + +typedef struct os_pool_cb { + void *pool; + uint8_t *markers; + uint32_t pool_sz; + uint32_t item_sz; + uint32_t currentIndex; +} os_pool_cb_t; + +/** + * @brief Create and Initialize a memory pool + * @param pool_def memory pool definition referenced with \ref osPool. + * @retval memory pool ID for reference by other functions or NULL in case of error. + * @note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS. + */ +osPoolId osPoolCreate(const osPoolDef_t *pool_def) { +#if (configSUPPORT_DYNAMIC_ALLOCATION == 1) + osPoolId thePool; + int itemSize = 4 * ((pool_def->item_sz + 3) / 4); + uint32_t i; + + /* First have to allocate memory for the pool control block. */ + thePool = pvPortMalloc(sizeof(os_pool_cb_t)); + + if (thePool) { + thePool->pool_sz = pool_def->pool_sz; + thePool->item_sz = itemSize; + thePool->currentIndex = 0; + + /* Memory for markers */ + thePool->markers = pvPortMalloc(pool_def->pool_sz); + + if (thePool->markers) { + /* Now allocate the pool itself. */ + thePool->pool = pvPortMalloc(pool_def->pool_sz * itemSize); + + if (thePool->pool) { + for (i = 0; i < pool_def->pool_sz; i++) { + thePool->markers[i] = 0; + } + } else { + vPortFree(thePool->markers); + vPortFree(thePool); + thePool = NULL; + } + } else { + vPortFree(thePool); + thePool = NULL; + } + } + + return thePool; + +#else + return NULL; +#endif +} + +/** + * @brief Allocate a memory block from a memory pool + * @param pool_id memory pool ID obtain referenced with \ref osPoolCreate. + * @retval address of the allocated memory block or NULL in case of no memory available. + * @note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS. + */ +void *osPoolAlloc(osPoolId pool_id) { + int dummy = 0; + void *p = NULL; + uint32_t i; + uint32_t index; + + if (inHandlerMode()) { + dummy = portSET_INTERRUPT_MASK_FROM_ISR(); + } else { + vPortEnterCritical(); + } + + for (i = 0; i < pool_id->pool_sz; i++) { + index = pool_id->currentIndex + i; + if (index >= pool_id->pool_sz) { + index = 0; + } + + if (pool_id->markers[index] == 0) { + pool_id->markers[index] = 1; + p = (void *)((uint32_t)(pool_id->pool) + (index * pool_id->item_sz)); + pool_id->currentIndex = index; + break; + } + } + + if (inHandlerMode()) { + portCLEAR_INTERRUPT_MASK_FROM_ISR(dummy); + } else { + vPortExitCritical(); + } + + return p; +} + +/** + * @brief Allocate a memory block from a memory pool and set memory block to zero + * @param pool_id memory pool ID obtain referenced with \ref osPoolCreate. + * @retval address of the allocated memory block or NULL in case of no memory available. + * @note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS. + */ +void *osPoolCAlloc(osPoolId pool_id) { + void *p = osPoolAlloc(pool_id); + + if (p != NULL) { + memset(p, 0, sizeof(pool_id->pool_sz)); + } + + return p; +} + +/** + * @brief Return an allocated memory block back to a specific memory pool + * @param pool_id memory pool ID obtain referenced with \ref osPoolCreate. + * @param block address of the allocated memory block that is returned to the memory pool. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS. + */ +osStatus osPoolFree(osPoolId pool_id, void *block) { + uint32_t index; + + if (pool_id == NULL) { + return osErrorParameter; + } + + if (block == NULL) { + return osErrorParameter; + } + + if (block < pool_id->pool) { + return osErrorParameter; + } + + index = (uint32_t)block - (uint32_t)(pool_id->pool); + if (index % pool_id->item_sz) { + return osErrorParameter; + } + index = index / pool_id->item_sz; + if (index >= pool_id->pool_sz) { + return osErrorParameter; + } + + pool_id->markers[index] = 0; + + return osOK; +} + +#endif /* Use Memory Pool Management */ + +/******************* Message Queue Management Functions *********************/ + +#if (defined(osFeature_MessageQ) && (osFeature_MessageQ != 0)) /* Use Message Queues */ + +/** + * @brief Create and Initialize a Message Queue + * @param queue_def queue definition referenced with \ref osMessageQ. + * @param thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL. + * @retval message queue ID for reference by other functions or NULL in case of error. + * @note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS. + */ +osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, osThreadId thread_id) { + (void)thread_id; + +#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) + + if ((queue_def->buffer != NULL) && (queue_def->controlblock != NULL)) { + return xQueueCreateStatic(queue_def->queue_sz, queue_def->item_sz, queue_def->buffer, queue_def->controlblock); + } else { + return xQueueCreate(queue_def->queue_sz, queue_def->item_sz); + } +#elif (configSUPPORT_STATIC_ALLOCATION == 1) + return xQueueCreateStatic(queue_def->queue_sz, queue_def->item_sz, queue_def->buffer, queue_def->controlblock); +#else + return xQueueCreate(queue_def->queue_sz, queue_def->item_sz); +#endif +} + +/** + * @brief Put a Message to a Queue. + * @param queue_id message queue ID obtained with \ref osMessageCreate. + * @param info message information. + * @param millisec timeout value or 0 in case of no time-out. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS. + */ +osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec) { + portBASE_TYPE taskWoken = pdFALSE; + TickType_t ticks; + + ticks = millisec / portTICK_PERIOD_MS; + if (ticks == 0) { + ticks = 1; + } + + if (inHandlerMode()) { + if (xQueueSendFromISR(queue_id, &info, &taskWoken) != pdTRUE) { + return osErrorOS; + } + portEND_SWITCHING_ISR(taskWoken); + } else { + if (xQueueSend(queue_id, &info, ticks) != pdTRUE) { + return osErrorOS; + } + } + + return osOK; +} + +/** + * @brief Get a Message or Wait for a Message from a Queue. + * @param queue_id message queue ID obtained with \ref osMessageCreate. + * @param millisec timeout value or 0 in case of no time-out. + * @retval event information that includes status code. + * @note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS. + */ +osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec) { + portBASE_TYPE taskWoken; + TickType_t ticks; + osEvent event; + + event.def.message_id = queue_id; + event.value.v = 0; + + if (queue_id == NULL) { + event.status = osErrorParameter; + return event; + } + + taskWoken = pdFALSE; + + ticks = 0; + if (millisec == osWaitForever) { + ticks = portMAX_DELAY; + } else if (millisec != 0) { + ticks = millisec / portTICK_PERIOD_MS; + if (ticks == 0) { + ticks = 1; + } + } + + if (inHandlerMode()) { + if (xQueueReceiveFromISR(queue_id, &event.value.v, &taskWoken) == pdTRUE) { + /* We have mail */ + event.status = osEventMessage; + } else { + event.status = osOK; + } + portEND_SWITCHING_ISR(taskWoken); + } else { + if (xQueueReceive(queue_id, &event.value.v, ticks) == pdTRUE) { + /* We have mail */ + event.status = osEventMessage; + } else { + event.status = (ticks == 0) ? osOK : osEventTimeout; + } + } + + return event; +} + +#endif /* Use Message Queues */ + +/******************** Mail Queue Management Functions ***********************/ +#if (defined(osFeature_MailQ) && (osFeature_MailQ != 0)) /* Use Mail Queues */ + +typedef struct os_mailQ_cb { + const osMailQDef_t *queue_def; + QueueHandle_t handle; + osPoolId pool; +} os_mailQ_cb_t; + +/** + * @brief Create and Initialize mail queue + * @param queue_def reference to the mail queue definition obtain with \ref osMailQ + * @param thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL. + * @retval mail queue ID for reference by other functions or NULL in case of error. + * @note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS. + */ +osMailQId osMailCreate(const osMailQDef_t *queue_def, osThreadId thread_id) { +#if (configSUPPORT_DYNAMIC_ALLOCATION == 1) + (void)thread_id; + + osPoolDef_t pool_def = {queue_def->queue_sz, queue_def->item_sz, NULL}; + + /* Create a mail queue control block */ + + *(queue_def->cb) = pvPortMalloc(sizeof(struct os_mailQ_cb)); + + if (*(queue_def->cb) == NULL) { + return NULL; + } + (*(queue_def->cb))->queue_def = queue_def; + + /* Create a queue in FreeRTOS */ + (*(queue_def->cb))->handle = xQueueCreate(queue_def->queue_sz, sizeof(void *)); + + if ((*(queue_def->cb))->handle == NULL) { + vPortFree(*(queue_def->cb)); + return NULL; + } + + /* Create a mail pool */ + (*(queue_def->cb))->pool = osPoolCreate(&pool_def); + if ((*(queue_def->cb))->pool == NULL) { + // TODO: Delete queue. How to do it in FreeRTOS? + vPortFree(*(queue_def->cb)); + return NULL; + } + + return *(queue_def->cb); +#else + return NULL; +#endif +} + +/** + * @brief Allocate a memory block from a mail + * @param queue_id mail queue ID obtained with \ref osMailCreate. + * @param millisec timeout value or 0 in case of no time-out. + * @retval pointer to memory block that can be filled with mail or NULL in case error. + * @note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS. + */ +void *osMailAlloc(osMailQId queue_id, uint32_t millisec) { + (void)millisec; + void *p; + + if (queue_id == NULL) { + return NULL; + } + + p = osPoolAlloc(queue_id->pool); + + return p; +} + +/** + * @brief Allocate a memory block from a mail and set memory block to zero + * @param queue_id mail queue ID obtained with \ref osMailCreate. + * @param millisec timeout value or 0 in case of no time-out. + * @retval pointer to memory block that can be filled with mail or NULL in case error. + * @note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS. + */ +void *osMailCAlloc(osMailQId queue_id, uint32_t millisec) { + uint32_t i; + void *p = osMailAlloc(queue_id, millisec); + + if (p) { + for (i = 0; i < queue_id->queue_def->item_sz; i++) { + ((uint8_t *)p)[i] = 0; + } + } + + return p; +} + +/** + * @brief Put a mail to a queue + * @param queue_id mail queue ID obtained with \ref osMailCreate. + * @param mail memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS. + */ +osStatus osMailPut(osMailQId queue_id, void *mail) { + portBASE_TYPE taskWoken; + + if (queue_id == NULL) { + return osErrorParameter; + } + + taskWoken = pdFALSE; + + if (inHandlerMode()) { + if (xQueueSendFromISR(queue_id->handle, &mail, &taskWoken) != pdTRUE) { + return osErrorOS; + } + portEND_SWITCHING_ISR(taskWoken); + } else { + if (xQueueSend(queue_id->handle, &mail, 0) != pdTRUE) { + return osErrorOS; + } + } + + return osOK; +} + +/** + * @brief Get a mail from a queue + * @param queue_id mail queue ID obtained with \ref osMailCreate. + * @param millisec timeout value or 0 in case of no time-out + * @retval event that contains mail information or error code. + * @note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS. + */ +osEvent osMailGet(osMailQId queue_id, uint32_t millisec) { + portBASE_TYPE taskWoken; + TickType_t ticks; + osEvent event; + + event.def.mail_id = queue_id; + + if (queue_id == NULL) { + event.status = osErrorParameter; + return event; + } + + taskWoken = pdFALSE; + + ticks = 0; + if (millisec == osWaitForever) { + ticks = portMAX_DELAY; + } else if (millisec != 0) { + ticks = millisec / portTICK_PERIOD_MS; + if (ticks == 0) { + ticks = 1; + } + } + + if (inHandlerMode()) { + if (xQueueReceiveFromISR(queue_id->handle, &event.value.p, &taskWoken) == pdTRUE) { + /* We have mail */ + event.status = osEventMail; + } else { + event.status = osOK; + } + portEND_SWITCHING_ISR(taskWoken); + } else { + if (xQueueReceive(queue_id->handle, &event.value.p, ticks) == pdTRUE) { + /* We have mail */ + event.status = osEventMail; + } else { + event.status = (ticks == 0) ? osOK : osEventTimeout; + } + } + + return event; +} + +/** + * @brief Free a memory block from a mail + * @param queue_id mail queue ID obtained with \ref osMailCreate. + * @param mail pointer to the memory block that was obtained with \ref osMailGet. + * @retval status code that indicates the execution status of the function. + * @note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS. + */ +osStatus osMailFree(osMailQId queue_id, void *mail) { + if (queue_id == NULL) { + return osErrorParameter; + } + + return osPoolFree(queue_id->pool, mail); +} +#endif /* Use Mail Queues */ + +/*************************** Additional specific APIs to Free RTOS ************/ +/** + * @brief Handles the tick increment + * @param none. + * @retval none. + */ +void osSystickHandler(void) { + +#if (INCLUDE_xTaskGetSchedulerState == 1) + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { +#endif /* INCLUDE_xTaskGetSchedulerState */ + xPortSysTickHandler(); +#if (INCLUDE_xTaskGetSchedulerState == 1) + } +#endif /* INCLUDE_xTaskGetSchedulerState */ +} + +#if (INCLUDE_eTaskGetState == 1) +/** + * @brief Obtain the state of any thread. + * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. + * @retval the stae of the thread, states are encoded by the osThreadState enumerated type. + */ +osThreadState osThreadGetState(osThreadId thread_id) { + eTaskState ThreadState; + osThreadState result; + + ThreadState = eTaskGetState(thread_id); + + switch (ThreadState) { + case eRunning: + result = osThreadRunning; + break; + case eReady: + result = osThreadReady; + break; + case eBlocked: + result = osThreadBlocked; + break; + case eSuspended: + result = osThreadSuspended; + break; + case eDeleted: + result = osThreadDeleted; + break; + default: + result = osThreadError; + } + + return result; +} +#endif /* INCLUDE_eTaskGetState */ + +#if (INCLUDE_eTaskGetState == 1) +/** + * @brief Check if a thread is already suspended or not. + * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. + * @retval status code that indicates the execution status of the function. + */ +osStatus osThreadIsSuspended(osThreadId thread_id) { + if (eTaskGetState(thread_id) == eSuspended) + return osOK; + else + return osErrorOS; +} +#endif /* INCLUDE_eTaskGetState */ +/** + * @brief Suspend execution of a thread. + * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. + * @retval status code that indicates the execution status of the function. + */ +osStatus osThreadSuspend(osThreadId thread_id) { +#if (INCLUDE_vTaskSuspend == 1) + vTaskSuspend(thread_id); + + return osOK; +#else + return osErrorResource; +#endif +} + +/** + * @brief Resume execution of a suspended thread. + * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. + * @retval status code that indicates the execution status of the function. + */ +osStatus osThreadResume(osThreadId thread_id) { +#if (INCLUDE_vTaskSuspend == 1) + if (inHandlerMode()) { + if (xTaskResumeFromISR(thread_id) == pdTRUE) { + portYIELD_FROM_ISR(pdTRUE); + } + } else { + vTaskResume(thread_id); + } + return osOK; +#else + return osErrorResource; +#endif +} + +/** + * @brief Suspend execution of a all active threads. + * @retval status code that indicates the execution status of the function. + */ +osStatus osThreadSuspendAll(void) { + vTaskSuspendAll(); + + return osOK; +} + +/** + * @brief Resume execution of a all suspended threads. + * @retval status code that indicates the execution status of the function. + */ +osStatus osThreadResumeAll(void) { + if (xTaskResumeAll() == pdTRUE) + return osOK; + else + return osErrorOS; +} + +/** + * @brief Delay a task until a specified time + * @param PreviousWakeTime Pointer to a variable that holds the time at which the + * task was last unblocked. PreviousWakeTime must be initialised with the current time + * prior to its first use (PreviousWakeTime = osKernelSysTick() ) + * @param millisec time delay value + * @retval status code that indicates the execution status of the function. + */ +osStatus osDelayUntil(uint32_t *PreviousWakeTime, uint32_t millisec) { +#if INCLUDE_vTaskDelayUntil + TickType_t ticks = (millisec / portTICK_PERIOD_MS); + vTaskDelayUntil((TickType_t *)PreviousWakeTime, ticks ? ticks : 1); + + return osOK; +#else + (void)millisec; + (void)PreviousWakeTime; + + return osErrorResource; +#endif +} + +/** + * @brief Abort the delay for a specific thread + * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId + * @retval status code that indicates the execution status of the function. + */ +osStatus osAbortDelay(osThreadId thread_id) { +#if INCLUDE_xTaskAbortDelay + + xTaskAbortDelay(thread_id); + + return osOK; +#else + (void)thread_id; + + return osErrorResource; +#endif +} + +/** + * @brief Lists all the current threads, along with their current state + * and stack usage high water mark. + * @param buffer A buffer into which the above mentioned details + * will be written + * @retval status code that indicates the execution status of the function. + */ +osStatus osThreadList(uint8_t *buffer) { +#if ((configUSE_TRACE_FACILITY == 1) && (configUSE_STATS_FORMATTING_FUNCTIONS == 1)) + vTaskList((char *)buffer); +#endif + return osOK; +} + +/** + * @brief Receive an item from a queue without removing the item from the queue. + * @param queue_id message queue ID obtained with \ref osMessageCreate. + * @param millisec timeout value or 0 in case of no time-out. + * @retval event information that includes status code. + */ +osEvent osMessagePeek(osMessageQId queue_id, uint32_t millisec) { + TickType_t ticks; + osEvent event; + + event.def.message_id = queue_id; + + if (queue_id == NULL) { + event.status = osErrorParameter; + return event; + } + + ticks = 0; + if (millisec == osWaitForever) { + ticks = portMAX_DELAY; + } else if (millisec != 0) { + ticks = millisec / portTICK_PERIOD_MS; + if (ticks == 0) { + ticks = 1; + } + } + + if (xQueuePeek(queue_id, &event.value.v, ticks) == pdTRUE) { + /* We have mail */ + event.status = osEventMessage; + } else { + event.status = (ticks == 0) ? osOK : osEventTimeout; + } + + return event; +} + +/** + * @brief Get the number of messaged stored in a queue. + * @param queue_id message queue ID obtained with \ref osMessageCreate. + * @retval number of messages stored in a queue. + */ +uint32_t osMessageWaiting(osMessageQId queue_id) { + if (inHandlerMode()) { + return uxQueueMessagesWaitingFromISR(queue_id); + } else { + return uxQueueMessagesWaiting(queue_id); + } +} + +/** + * @brief Get the available space in a message queue. + * @param queue_id message queue ID obtained with \ref osMessageCreate. + * @retval available space in a message queue. + */ +uint32_t osMessageAvailableSpace(osMessageQId queue_id) { return uxQueueSpacesAvailable(queue_id); } + +/** + * @brief Delete a Message Queue + * @param queue_id message queue ID obtained with \ref osMessageCreate. + * @retval status code that indicates the execution status of the function. + */ +osStatus osMessageDelete(osMessageQId queue_id) { + if (inHandlerMode()) { + return osErrorISR; + } + + vQueueDelete(queue_id); + + return osOK; +} + +/** + * @brief Create and Initialize a Recursive Mutex + * @param mutex_def mutex definition referenced with \ref osMutex. + * @retval mutex ID for reference by other functions or NULL in case of error.. + */ +osMutexId osRecursiveMutexCreate(const osMutexDef_t *mutex_def) { +#if (configUSE_RECURSIVE_MUTEXES == 1) +#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) + + if (mutex_def->controlblock != NULL) { + return xSemaphoreCreateRecursiveMutexStatic(mutex_def->controlblock); + } else { + return xSemaphoreCreateRecursiveMutex(); + } +#elif (configSUPPORT_STATIC_ALLOCATION == 1) + return xSemaphoreCreateRecursiveMutexStatic(mutex_def->controlblock); +#else + return xSemaphoreCreateRecursiveMutex(); +#endif +#else + return NULL; +#endif +} + +/** + * @brief Release a Recursive Mutex + * @param mutex_id mutex ID obtained by \ref osRecursiveMutexCreate. + * @retval status code that indicates the execution status of the function. + */ +osStatus osRecursiveMutexRelease(osMutexId mutex_id) { +#if (configUSE_RECURSIVE_MUTEXES == 1) + osStatus result = osOK; + + if (xSemaphoreGiveRecursive(mutex_id) != pdTRUE) { + result = osErrorOS; + } + return result; +#else + return osErrorResource; +#endif +} + +/** + * @brief Release a Recursive Mutex + * @param mutex_id mutex ID obtained by \ref osRecursiveMutexCreate. + * @param millisec timeout value or 0 in case of no time-out. + * @retval status code that indicates the execution status of the function. + */ +osStatus osRecursiveMutexWait(osMutexId mutex_id, uint32_t millisec) { +#if (configUSE_RECURSIVE_MUTEXES == 1) + TickType_t ticks; + + if (mutex_id == NULL) { + return osErrorParameter; + } + + ticks = 0; + if (millisec == osWaitForever) { + ticks = portMAX_DELAY; + } else if (millisec != 0) { + ticks = millisec / portTICK_PERIOD_MS; + if (ticks == 0) { + ticks = 1; + } + } + + if (xSemaphoreTakeRecursive(mutex_id, ticks) != pdTRUE) { + return osErrorOS; + } + return osOK; +#else + return osErrorResource; +#endif +} + +/** + * @brief Returns the current count value of a counting semaphore + * @param semaphore_id semaphore_id ID obtained by \ref osSemaphoreCreate. + * @retval count value + */ +uint32_t osSemaphoreGetCount(osSemaphoreId semaphore_id) { return uxSemaphoreGetCount(semaphore_id); } diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h b/source/Middlewares/FreeRTOS/CMSIS_RTOS/cmsis_os.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h rename to source/Middlewares/FreeRTOS/CMSIS_RTOS/cmsis_os.h diff --git a/source/Middlewares/FreeRTOS/CMakeLists.txt b/source/Middlewares/FreeRTOS/CMakeLists.txt new file mode 100644 index 00000000..30ace3db --- /dev/null +++ b/source/Middlewares/FreeRTOS/CMakeLists.txt @@ -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 PUBLIC BSP BSPImplementation) +target_include_directories(FreeRTOS PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_RTOS) \ No newline at end of file diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/croutine.c b/source/Middlewares/FreeRTOS/croutine.c similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/croutine.c rename to source/Middlewares/FreeRTOS/croutine.c diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c b/source/Middlewares/FreeRTOS/event_groups.c similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c rename to source/Middlewares/FreeRTOS/event_groups.c diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h b/source/Middlewares/FreeRTOS/include/FreeRTOS.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h rename to source/Middlewares/FreeRTOS/include/FreeRTOS.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/StackMacros.h b/source/Middlewares/FreeRTOS/include/StackMacros.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/StackMacros.h rename to source/Middlewares/FreeRTOS/include/StackMacros.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/atomic.h b/source/Middlewares/FreeRTOS/include/atomic.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/atomic.h rename to source/Middlewares/FreeRTOS/include/atomic.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/croutine.h b/source/Middlewares/FreeRTOS/include/croutine.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/croutine.h rename to source/Middlewares/FreeRTOS/include/croutine.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/event_groups.h b/source/Middlewares/FreeRTOS/include/event_groups.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/event_groups.h rename to source/Middlewares/FreeRTOS/include/event_groups.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/list.h b/source/Middlewares/FreeRTOS/include/list.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/list.h rename to source/Middlewares/FreeRTOS/include/list.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/message_buffer.h b/source/Middlewares/FreeRTOS/include/message_buffer.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/message_buffer.h rename to source/Middlewares/FreeRTOS/include/message_buffer.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_prototypes.h b/source/Middlewares/FreeRTOS/include/mpu_prototypes.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_prototypes.h rename to source/Middlewares/FreeRTOS/include/mpu_prototypes.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_wrappers.h b/source/Middlewares/FreeRTOS/include/mpu_wrappers.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/mpu_wrappers.h rename to source/Middlewares/FreeRTOS/include/mpu_wrappers.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h b/source/Middlewares/FreeRTOS/include/portable.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h rename to source/Middlewares/FreeRTOS/include/portable.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/projdefs.h b/source/Middlewares/FreeRTOS/include/projdefs.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/projdefs.h rename to source/Middlewares/FreeRTOS/include/projdefs.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/queue.h b/source/Middlewares/FreeRTOS/include/queue.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/queue.h rename to source/Middlewares/FreeRTOS/include/queue.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/semphr.h b/source/Middlewares/FreeRTOS/include/semphr.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/semphr.h rename to source/Middlewares/FreeRTOS/include/semphr.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/stack_macros.h b/source/Middlewares/FreeRTOS/include/stack_macros.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/stack_macros.h rename to source/Middlewares/FreeRTOS/include/stack_macros.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/stream_buffer.h b/source/Middlewares/FreeRTOS/include/stream_buffer.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/stream_buffer.h rename to source/Middlewares/FreeRTOS/include/stream_buffer.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/task.h b/source/Middlewares/FreeRTOS/include/task.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/task.h rename to source/Middlewares/FreeRTOS/include/task.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/include/timers.h b/source/Middlewares/FreeRTOS/include/timers.h similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/include/timers.h rename to source/Middlewares/FreeRTOS/include/timers.h diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/list.c b/source/Middlewares/FreeRTOS/list.c similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/list.c rename to source/Middlewares/FreeRTOS/list.c diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/queue.c b/source/Middlewares/FreeRTOS/queue.c similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/queue.c rename to source/Middlewares/FreeRTOS/queue.c diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/tasks.c b/source/Middlewares/FreeRTOS/tasks.c similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/tasks.c rename to source/Middlewares/FreeRTOS/tasks.c diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/timers.c b/source/Middlewares/FreeRTOS/timers.c similarity index 100% rename from source/Middlewares/Third_Party/FreeRTOS/Source/timers.c rename to source/Middlewares/FreeRTOS/timers.c diff --git a/source/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c b/source/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c deleted file mode 100644 index 552f583c..00000000 --- a/source/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c +++ /dev/null @@ -1,1881 +0,0 @@ -/* ---------------------------------------------------------------------- - * $Date: 5. February 2013 - * $Revision: V1.02 - * - * Project: CMSIS-RTOS API - * Title: cmsis_os.c - * - * Version 0.02 - * Initial Proposal Phase - * Version 0.03 - * osKernelStart added, optional feature: main started as thread - * osSemaphores have standard behavior - * osTimerCreate does not start the timer, added osTimerStart - * osThreadPass is renamed to osThreadYield - * Version 1.01 - * Support for C++ interface - * - const attribute removed from the osXxxxDef_t typedef's - * - const attribute added to the osXxxxDef macros - * Added: osTimerDelete, osMutexDelete, osSemaphoreDelete - * Added: osKernelInitialize - * Version 1.02 - * Control functions for short timeouts in microsecond resolution: - * Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec - * Removed: osSignalGet - * - * - *---------------------------------------------------------------------------- - * - * Portions Copyright � 2016 STMicroelectronics International N.V. All rights reserved. - * Portions Copyright (c) 2013 ARM LIMITED - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *---------------------------------------------------------------------------*/ - -/** - ****************************************************************************** - * @file cmsis_os.c - * @author MCD Application Team - * @date 03-March-2017 - * @brief CMSIS-RTOS API implementation for FreeRTOS V9.0.0 - ****************************************************************************** - * @attention - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -#include -#include "cmsis_os.h" - -/* - * ARM Compiler 4/5 - */ -#if defined(__CC_ARM) - -#define __ASM __asm -#define __INLINE __inline -#define __STATIC_INLINE static __inline -#include "cmsis_armcc.h" - -/* - * GNU Compiler - */ -#elif defined(__GNUC__) - -#define __ASM __asm /*!< asm keyword for GNU Compiler */ -#define __INLINE inline /*!< inline keyword for GNU Compiler */ -#define __STATIC_INLINE static inline -uint32_t __get_IPSR(void); -// #include "cmsis_gcc.h" - -/* - * IAR Compiler - */ -#elif defined(__ICCARM__) - -#ifndef __ASM -#define __ASM __asm -#endif -#ifndef __INLINE -#define __INLINE inline -#endif -#ifndef __STATIC_INLINE -#define __STATIC_INLINE static inline -#endif - -#include -#endif - -extern void xPortSysTickHandler(void); - -/* Convert from CMSIS type osPriority to FreeRTOS priority number */ -static unsigned portBASE_TYPE makeFreeRtosPriority(osPriority priority) -{ - unsigned portBASE_TYPE fpriority = tskIDLE_PRIORITY; - - if (priority != osPriorityError) - { - fpriority += (priority - osPriorityIdle); - } - - return fpriority; -} - -#if (INCLUDE_uxTaskPriorityGet == 1) -/* Convert from FreeRTOS priority number to CMSIS type osPriority */ -static osPriority makeCmsisPriority(unsigned portBASE_TYPE fpriority) -{ - osPriority priority = osPriorityError; - - if ((fpriority - tskIDLE_PRIORITY) <= (osPriorityRealtime - osPriorityIdle)) - { - priority = (osPriority)((int)osPriorityIdle + (int)(fpriority - tskIDLE_PRIORITY)); - } - - return priority; -} -#endif - -/* Determine whether we are in thread mode or handler mode. */ -static int inHandlerMode(void) -{ - return __get_IPSR() != 0; -} - -/*********************** Kernel Control Functions *****************************/ -/** -* @brief Initialize the RTOS Kernel for creating objects. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS. -*/ -osStatus osKernelInitialize(void); - -/** -* @brief Start the RTOS Kernel with executing the specified thread. -* @param thread_def thread definition referenced with \ref osThread. -* @param argument pointer that is passed to the thread function as start argument. -* @retval status code that indicates the execution status of the function -* @note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS. -*/ -osStatus osKernelStart(void) -{ - vTaskStartScheduler(); - - return osOK; -} - -/** -* @brief Check if the RTOS kernel is already started -* @param None -* @retval (0) RTOS is not started -* (1) RTOS is started -* (-1) if this feature is disabled in FreeRTOSConfig.h -* @note MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every CMSIS-RTOS. -*/ -int32_t osKernelRunning(void) -{ -#if ((INCLUDE_xTaskGetSchedulerState == 1) || (configUSE_TIMERS == 1)) - if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) - return 0; - else - return 1; -#else - return (-1); -#endif -} - -#if (defined(osFeature_SysTick) && (osFeature_SysTick != 0)) // System Timer available -/** -* @brief Get the value of the Kernel SysTick timer -* @param None -* @retval None -* @note MUST REMAIN UNCHANGED: \b osKernelSysTick shall be consistent in every CMSIS-RTOS. -*/ -uint32_t osKernelSysTick(void) -{ - if (inHandlerMode()) - { - return xTaskGetTickCountFromISR(); - } - else - { - return xTaskGetTickCount(); - } -} -#endif // System Timer available -/*********************** Thread Management *****************************/ -/** -* @brief Create a thread and add it to Active Threads and set it to state READY. -* @param thread_def thread definition referenced with \ref osThread. -* @param argument pointer that is passed to the thread function as start argument. -* @retval thread ID for reference by other functions or NULL in case of error. -* @note MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS. -*/ -osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument) -{ - TaskHandle_t handle; - -#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) - if ((thread_def->buffer != NULL) && (thread_def->controlblock != NULL)) - { - handle = xTaskCreateStatic((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, - thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), - thread_def->buffer, thread_def->controlblock); - } - else - { - if (xTaskCreate((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, - thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), - &handle) != pdPASS) - { - return NULL; - } - } -#elif (configSUPPORT_STATIC_ALLOCATION == 1) - - handle = xTaskCreateStatic((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, - thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), - thread_def->buffer, thread_def->controlblock); -#else - if (xTaskCreate((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, - thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), - &handle) != pdPASS) - { - return NULL; - } -#endif - - return handle; -} - -/** -* @brief Return the thread ID of the current running thread. -* @retval thread ID for reference by other functions or NULL in case of error. -* @note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS. -*/ -osThreadId osThreadGetId(void) -{ -#if ((INCLUDE_xTaskGetCurrentTaskHandle == 1) || (configUSE_MUTEXES == 1)) - return xTaskGetCurrentTaskHandle(); -#else - return NULL; -#endif -} - -/** -* @brief Terminate execution of a thread and remove it from Active Threads. -* @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be consistent in every CMSIS-RTOS. -*/ -osStatus osThreadTerminate(osThreadId thread_id) -{ -#if (INCLUDE_vTaskDelete == 1) - vTaskDelete(thread_id); - return osOK; -#else - return osErrorOS; -#endif -} - -/** -* @brief Pass control to next thread that is in state \b READY. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS. -*/ -osStatus osThreadYield(void) -{ - taskYIELD(); - - return osOK; -} - -/** -* @brief Change priority of an active thread. -* @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. -* @param priority new priority value for the thread function. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS. -*/ -osStatus osThreadSetPriority(osThreadId thread_id, osPriority priority) -{ -#if (INCLUDE_vTaskPrioritySet == 1) - vTaskPrioritySet(thread_id, makeFreeRtosPriority(priority)); - return osOK; -#else - return osErrorOS; -#endif -} - -/** -* @brief Get current priority of an active thread. -* @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. -* @retval current priority value of the thread function. -* @note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS. -*/ -osPriority osThreadGetPriority(osThreadId thread_id) -{ -#if (INCLUDE_uxTaskPriorityGet == 1) - if (inHandlerMode()) - { - return makeCmsisPriority(uxTaskPriorityGetFromISR(thread_id)); - } - else - { - return makeCmsisPriority(uxTaskPriorityGet(thread_id)); - } -#else - return osPriorityError; -#endif -} - -/*********************** Generic Wait Functions *******************************/ -/** -* @brief Wait for Timeout (Time Delay) -* @param millisec time delay value -* @retval status code that indicates the execution status of the function. -*/ -osStatus osDelay(uint32_t millisec) -{ -#if INCLUDE_vTaskDelay - TickType_t ticks = millisec / portTICK_PERIOD_MS; - - vTaskDelay(ticks ? ticks : 1); /* Minimum delay = 1 tick */ - - return osOK; -#else - (void)millisec; - - return osErrorResource; -#endif -} - -#if (defined(osFeature_Wait) && (osFeature_Wait != 0)) /* Generic Wait available */ -/** -* @brief Wait for Signal, Message, Mail, or Timeout -* @param millisec timeout value or 0 in case of no time-out -* @retval event that contains signal, message, or mail information or error code. -* @note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS. -*/ -osEvent osWait(uint32_t millisec); - -#endif /* Generic Wait available */ - -/*********************** Timer Management Functions ***************************/ -/** -* @brief Create a timer. -* @param timer_def timer object referenced with \ref osTimer. -* @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior. -* @param argument argument to the timer call back function. -* @retval timer ID for reference by other functions or NULL in case of error. -* @note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS. -*/ -osTimerId osTimerCreate(const osTimerDef_t *timer_def, os_timer_type type, void *argument) -{ -#if (configUSE_TIMERS == 1) - -#if ((configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1)) - if (timer_def->controlblock != NULL) - { - return xTimerCreateStatic((const char *)"", - 1, // period should be filled when starting the Timer using osTimerStart - (type == osTimerPeriodic) ? pdTRUE : pdFALSE, - (void *)argument, - (TaskFunction_t)timer_def->ptimer, - (StaticTimer_t *)timer_def->controlblock); - } - else - { - return xTimerCreate((const char *)"", - 1, // period should be filled when starting the Timer using osTimerStart - (type == osTimerPeriodic) ? pdTRUE : pdFALSE, - (void *)argument, - (TaskFunction_t)timer_def->ptimer); - } -#elif (configSUPPORT_STATIC_ALLOCATION == 1) - return xTimerCreateStatic((const char *)"", - 1, // period should be filled when starting the Timer using osTimerStart - (type == osTimerPeriodic) ? pdTRUE : pdFALSE, - (void *)argument, - (TaskFunction_t)timer_def->ptimer, - (StaticTimer_t *)timer_def->controlblock); -#else - return xTimerCreate((const char *)"", - 1, // period should be filled when starting the Timer using osTimerStart - (type == osTimerPeriodic) ? pdTRUE : pdFALSE, - (void *)argument, - (TaskFunction_t)timer_def->ptimer); -#endif - -#else - return NULL; -#endif -} - -/** -* @brief Start or restart a timer. -* @param timer_id timer ID obtained by \ref osTimerCreate. -* @param millisec time delay value of the timer. -* @retval status code that indicates the execution status of the function -* @note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS. -*/ -osStatus osTimerStart(osTimerId timer_id, uint32_t millisec) -{ - osStatus result = osOK; -#if (configUSE_TIMERS == 1) - portBASE_TYPE taskWoken = pdFALSE; - TickType_t ticks = millisec / portTICK_PERIOD_MS; - - if (ticks == 0) - ticks = 1; - - if (inHandlerMode()) - { - if (xTimerChangePeriodFromISR(timer_id, ticks, &taskWoken) != pdPASS) - { - result = osErrorOS; - } - else - { - portEND_SWITCHING_ISR(taskWoken); - } - } - else - { - if (xTimerChangePeriod(timer_id, ticks, 0) != pdPASS) - result = osErrorOS; - } - -#else - result = osErrorOS; -#endif - return result; -} - -/** -* @brief Stop a timer. -* @param timer_id timer ID obtained by \ref osTimerCreate -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS. -*/ -osStatus osTimerStop(osTimerId timer_id) -{ - osStatus result = osOK; -#if (configUSE_TIMERS == 1) - portBASE_TYPE taskWoken = pdFALSE; - - if (inHandlerMode()) - { - if (xTimerStopFromISR(timer_id, &taskWoken) != pdPASS) - { - return osErrorOS; - } - portEND_SWITCHING_ISR(taskWoken); - } - else - { - if (xTimerStop(timer_id, 0) != pdPASS) - { - result = osErrorOS; - } - } -#else - result = osErrorOS; -#endif - return result; -} - -/** -* @brief Delete a timer. -* @param timer_id timer ID obtained by \ref osTimerCreate -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS. -*/ -osStatus osTimerDelete(osTimerId timer_id) -{ - osStatus result = osOK; - -#if (configUSE_TIMERS == 1) - - if (inHandlerMode()) - { - return osErrorISR; - } - else - { - if ((xTimerDelete(timer_id, osWaitForever)) != pdPASS) - { - result = osErrorOS; - } - } - -#else - result = osErrorOS; -#endif - - return result; -} - -/*************************** Signal Management ********************************/ -/** -* @brief Set the specified Signal Flags of an active thread. -* @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. -* @param signals specifies the signal flags of the thread that should be set. -* @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. -* @note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS. -*/ -int32_t osSignalSet(osThreadId thread_id, int32_t signal) -{ -#if (configUSE_TASK_NOTIFICATIONS == 1) - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - uint32_t ulPreviousNotificationValue = 0; - - if (inHandlerMode()) - { - if (xTaskGenericNotifyFromISR(thread_id, (uint32_t)signal, eSetBits, &ulPreviousNotificationValue, &xHigherPriorityTaskWoken) != pdPASS) - return 0x80000000; - - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); - } - else if (xTaskGenericNotify(thread_id, (uint32_t)signal, eSetBits, &ulPreviousNotificationValue) != pdPASS) - return 0x80000000; - - return ulPreviousNotificationValue; -#else - (void)thread_id; - (void)signal; - - return 0x80000000; /* Task Notification not supported */ -#endif -} - -/** -* @brief Clear the specified Signal Flags of an active thread. -* @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. -* @param signals specifies the signal flags of the thread that shall be cleared. -* @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. -* @note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS. -*/ -int32_t osSignalClear(osThreadId thread_id, int32_t signal); - -/** -* @brief Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread. -* @param signals wait until all specified signal flags set or 0 for any single signal flag. -* @param millisec timeout value or 0 in case of no time-out. -* @retval event flag information or error code. -* @note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS. -*/ -osEvent osSignalWait(int32_t signals, uint32_t millisec) -{ - osEvent ret; - -#if (configUSE_TASK_NOTIFICATIONS == 1) - - TickType_t ticks; - - ret.value.signals = 0; - ticks = 0; - if (millisec == osWaitForever) - { - ticks = portMAX_DELAY; - } - else if (millisec != 0) - { - ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) - { - ticks = 1; - } - } - - if (inHandlerMode()) - { - ret.status = osErrorISR; /*Not allowed in ISR*/ - } - else - { - if (xTaskNotifyWait(0, (uint32_t)signals, (uint32_t *)&ret.value.signals, ticks) != pdTRUE) - { - if (ticks == 0) - ret.status = osOK; - else - ret.status = osEventTimeout; - } - else if (ret.value.signals < 0) - { - ret.status = osErrorValue; - } - else - ret.status = osEventSignal; - } -#else - (void)signals; - (void)millisec; - - ret.status = osErrorOS; /* Task Notification not supported */ -#endif - - return ret; -} - -/**************************** Mutex Management ********************************/ -/** -* @brief Create and Initialize a Mutex object -* @param mutex_def mutex definition referenced with \ref osMutex. -* @retval mutex ID for reference by other functions or NULL in case of error. -* @note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS. -*/ -osMutexId osMutexCreate(const osMutexDef_t *mutex_def) -{ -#if (configUSE_MUTEXES == 1) - -#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) - - if (mutex_def->controlblock != NULL) - { - return xSemaphoreCreateMutexStatic(mutex_def->controlblock); - } - else - { - return xSemaphoreCreateMutex(); - } -#elif (configSUPPORT_STATIC_ALLOCATION == 1) - return xSemaphoreCreateMutexStatic(mutex_def->controlblock); -#else - return xSemaphoreCreateMutex(); -#endif -#else - return NULL; -#endif -} - -/** -* @brief Wait until a Mutex becomes available -* @param mutex_id mutex ID obtained by \ref osMutexCreate. -* @param millisec timeout value or 0 in case of no time-out. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS. -*/ -osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec) -{ - TickType_t ticks; - portBASE_TYPE taskWoken = pdFALSE; - - if (mutex_id == NULL) - { - return osErrorParameter; - } - - ticks = 0; - if (millisec == osWaitForever) - { - ticks = portMAX_DELAY; - } - else if (millisec != 0) - { - ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) - { - ticks = 1; - } - } - - if (inHandlerMode()) - { - if (xSemaphoreTakeFromISR(mutex_id, &taskWoken) != pdTRUE) - { - return osErrorOS; - } - portEND_SWITCHING_ISR(taskWoken); - } - else if (xSemaphoreTake(mutex_id, ticks) != pdTRUE) - { - return osErrorOS; - } - - return osOK; -} - -/** -* @brief Release a Mutex that was obtained by \ref osMutexWait -* @param mutex_id mutex ID obtained by \ref osMutexCreate. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS. -*/ -osStatus osMutexRelease(osMutexId mutex_id) -{ - osStatus result = osOK; - portBASE_TYPE taskWoken = pdFALSE; - - if (inHandlerMode()) - { - if (xSemaphoreGiveFromISR(mutex_id, &taskWoken) != pdTRUE) - { - return osErrorOS; - } - portEND_SWITCHING_ISR(taskWoken); - } - else if (xSemaphoreGive(mutex_id) != pdTRUE) - { - result = osErrorOS; - } - return result; -} - -/** -* @brief Delete a Mutex -* @param mutex_id mutex ID obtained by \ref osMutexCreate. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS. -*/ -osStatus osMutexDelete(osMutexId mutex_id) -{ - if (inHandlerMode()) - { - return osErrorISR; - } - - vQueueDelete(mutex_id); - - return osOK; -} - -/******************** Semaphore Management Functions **************************/ - -#if (defined(osFeature_Semaphore) && (osFeature_Semaphore != 0)) - -/** -* @brief Create and Initialize a Semaphore object used for managing resources -* @param semaphore_def semaphore definition referenced with \ref osSemaphore. -* @param count number of available resources. -* @retval semaphore ID for reference by other functions or NULL in case of error. -* @note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS. -*/ -osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, int32_t count) -{ -#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) - - osSemaphoreId sema; - - if (semaphore_def->controlblock != NULL) - { - if (count == 1) - { - return xSemaphoreCreateBinaryStatic(semaphore_def->controlblock); - } - else - { -#if (configUSE_COUNTING_SEMAPHORES == 1) - return xSemaphoreCreateCountingStatic(count, count, semaphore_def->controlblock); -#else - return NULL; -#endif - } - } - else - { - if (count == 1) - { - vSemaphoreCreateBinary(sema); - return sema; - } - else - { -#if (configUSE_COUNTING_SEMAPHORES == 1) - return xSemaphoreCreateCounting(count, count); -#else - return NULL; -#endif - } - } -#elif (configSUPPORT_STATIC_ALLOCATION == 1) // configSUPPORT_DYNAMIC_ALLOCATION == 0 - if (count == 1) - { - return xSemaphoreCreateBinaryStatic(semaphore_def->controlblock); - } - else - { -#if (configUSE_COUNTING_SEMAPHORES == 1) - return xSemaphoreCreateCountingStatic(count, count, semaphore_def->controlblock); -#else - return NULL; -#endif - } -#else // configSUPPORT_STATIC_ALLOCATION == 0 && configSUPPORT_DYNAMIC_ALLOCATION == 1 - osSemaphoreId sema; - - if (count == 1) - { - vSemaphoreCreateBinary(sema); - return sema; - } - else - { -#if (configUSE_COUNTING_SEMAPHORES == 1) - return xSemaphoreCreateCounting(count, count); -#else - return NULL; -#endif - } -#endif -} - -/** -* @brief Wait until a Semaphore token becomes available -* @param semaphore_id semaphore object referenced with \ref osSemaphore. -* @param millisec timeout value or 0 in case of no time-out. -* @retval number of available tokens, or -1 in case of incorrect parameters. -* @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS. -*/ -int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec) -{ - TickType_t ticks; - portBASE_TYPE taskWoken = pdFALSE; - - if (semaphore_id == NULL) - { - return osErrorParameter; - } - - ticks = 0; - if (millisec == osWaitForever) - { - ticks = portMAX_DELAY; - } - else if (millisec != 0) - { - ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) - { - ticks = 1; - } - } - - if (inHandlerMode()) - { - if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) - { - return osErrorOS; - } - portEND_SWITCHING_ISR(taskWoken); - } - else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) - { - return osErrorOS; - } - - return osOK; -} - -/** -* @brief Release a Semaphore token -* @param semaphore_id semaphore object referenced with \ref osSemaphore. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS. -*/ -osStatus osSemaphoreRelease(osSemaphoreId semaphore_id) -{ - osStatus result = osOK; - portBASE_TYPE taskWoken = pdFALSE; - - if (inHandlerMode()) - { - if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) - { - return osErrorOS; - } - portEND_SWITCHING_ISR(taskWoken); - } - else - { - if (xSemaphoreGive(semaphore_id) != pdTRUE) - { - result = osErrorOS; - } - } - - return result; -} - -/** -* @brief Delete a Semaphore -* @param semaphore_id semaphore object referenced with \ref osSemaphore. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS. -*/ -osStatus osSemaphoreDelete(osSemaphoreId semaphore_id) -{ - if (inHandlerMode()) - { - return osErrorISR; - } - - vSemaphoreDelete(semaphore_id); - - return osOK; -} - -#endif /* Use Semaphores */ - -/******************* Memory Pool Management Functions ***********************/ - -#if (defined(osFeature_Pool) && (osFeature_Pool != 0)) - -//TODO -//This is a primitive and inefficient wrapper around the existing FreeRTOS memory management. -//A better implementation will have to modify heap_x.c! - -typedef struct os_pool_cb -{ - void *pool; - uint8_t *markers; - uint32_t pool_sz; - uint32_t item_sz; - uint32_t currentIndex; -} os_pool_cb_t; - -/** -* @brief Create and Initialize a memory pool -* @param pool_def memory pool definition referenced with \ref osPool. -* @retval memory pool ID for reference by other functions or NULL in case of error. -* @note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS. -*/ -osPoolId osPoolCreate(const osPoolDef_t *pool_def) -{ -#if (configSUPPORT_DYNAMIC_ALLOCATION == 1) - osPoolId thePool; - int itemSize = 4 * ((pool_def->item_sz + 3) / 4); - uint32_t i; - - /* First have to allocate memory for the pool control block. */ - thePool = pvPortMalloc(sizeof(os_pool_cb_t)); - - if (thePool) - { - thePool->pool_sz = pool_def->pool_sz; - thePool->item_sz = itemSize; - thePool->currentIndex = 0; - - /* Memory for markers */ - thePool->markers = pvPortMalloc(pool_def->pool_sz); - - if (thePool->markers) - { - /* Now allocate the pool itself. */ - thePool->pool = pvPortMalloc(pool_def->pool_sz * itemSize); - - if (thePool->pool) - { - for (i = 0; i < pool_def->pool_sz; i++) - { - thePool->markers[i] = 0; - } - } - else - { - vPortFree(thePool->markers); - vPortFree(thePool); - thePool = NULL; - } - } - else - { - vPortFree(thePool); - thePool = NULL; - } - } - - return thePool; - -#else - return NULL; -#endif -} - -/** -* @brief Allocate a memory block from a memory pool -* @param pool_id memory pool ID obtain referenced with \ref osPoolCreate. -* @retval address of the allocated memory block or NULL in case of no memory available. -* @note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS. -*/ -void *osPoolAlloc(osPoolId pool_id) -{ - int dummy = 0; - void *p = NULL; - uint32_t i; - uint32_t index; - - if (inHandlerMode()) - { - dummy = portSET_INTERRUPT_MASK_FROM_ISR(); - } - else - { - vPortEnterCritical(); - } - - for (i = 0; i < pool_id->pool_sz; i++) - { - index = pool_id->currentIndex + i; - if (index >= pool_id->pool_sz) - { - index = 0; - } - - if (pool_id->markers[index] == 0) - { - pool_id->markers[index] = 1; - p = (void *)((uint32_t)(pool_id->pool) + (index * pool_id->item_sz)); - pool_id->currentIndex = index; - break; - } - } - - if (inHandlerMode()) - { - portCLEAR_INTERRUPT_MASK_FROM_ISR(dummy); - } - else - { - vPortExitCritical(); - } - - return p; -} - -/** -* @brief Allocate a memory block from a memory pool and set memory block to zero -* @param pool_id memory pool ID obtain referenced with \ref osPoolCreate. -* @retval address of the allocated memory block or NULL in case of no memory available. -* @note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS. -*/ -void *osPoolCAlloc(osPoolId pool_id) -{ - void *p = osPoolAlloc(pool_id); - - if (p != NULL) - { - memset(p, 0, sizeof(pool_id->pool_sz)); - } - - return p; -} - -/** -* @brief Return an allocated memory block back to a specific memory pool -* @param pool_id memory pool ID obtain referenced with \ref osPoolCreate. -* @param block address of the allocated memory block that is returned to the memory pool. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS. -*/ -osStatus osPoolFree(osPoolId pool_id, void *block) -{ - uint32_t index; - - if (pool_id == NULL) - { - return osErrorParameter; - } - - if (block == NULL) - { - return osErrorParameter; - } - - if (block < pool_id->pool) - { - return osErrorParameter; - } - - index = (uint32_t)block - (uint32_t)(pool_id->pool); - if (index % pool_id->item_sz) - { - return osErrorParameter; - } - index = index / pool_id->item_sz; - if (index >= pool_id->pool_sz) - { - return osErrorParameter; - } - - pool_id->markers[index] = 0; - - return osOK; -} - -#endif /* Use Memory Pool Management */ - -/******************* Message Queue Management Functions *********************/ - -#if (defined(osFeature_MessageQ) && (osFeature_MessageQ != 0)) /* Use Message Queues */ - -/** -* @brief Create and Initialize a Message Queue -* @param queue_def queue definition referenced with \ref osMessageQ. -* @param thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL. -* @retval message queue ID for reference by other functions or NULL in case of error. -* @note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS. -*/ -osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, osThreadId thread_id) -{ - (void)thread_id; - -#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) - - if ((queue_def->buffer != NULL) && (queue_def->controlblock != NULL)) - { - return xQueueCreateStatic(queue_def->queue_sz, queue_def->item_sz, queue_def->buffer, queue_def->controlblock); - } - else - { - return xQueueCreate(queue_def->queue_sz, queue_def->item_sz); - } -#elif (configSUPPORT_STATIC_ALLOCATION == 1) - return xQueueCreateStatic(queue_def->queue_sz, queue_def->item_sz, queue_def->buffer, queue_def->controlblock); -#else - return xQueueCreate(queue_def->queue_sz, queue_def->item_sz); -#endif -} - -/** -* @brief Put a Message to a Queue. -* @param queue_id message queue ID obtained with \ref osMessageCreate. -* @param info message information. -* @param millisec timeout value or 0 in case of no time-out. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS. -*/ -osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec) -{ - portBASE_TYPE taskWoken = pdFALSE; - TickType_t ticks; - - ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) - { - ticks = 1; - } - - if (inHandlerMode()) - { - if (xQueueSendFromISR(queue_id, &info, &taskWoken) != pdTRUE) - { - return osErrorOS; - } - portEND_SWITCHING_ISR(taskWoken); - } - else - { - if (xQueueSend(queue_id, &info, ticks) != pdTRUE) - { - return osErrorOS; - } - } - - return osOK; -} - -/** -* @brief Get a Message or Wait for a Message from a Queue. -* @param queue_id message queue ID obtained with \ref osMessageCreate. -* @param millisec timeout value or 0 in case of no time-out. -* @retval event information that includes status code. -* @note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS. -*/ -osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec) -{ - portBASE_TYPE taskWoken; - TickType_t ticks; - osEvent event; - - event.def.message_id = queue_id; - event.value.v = 0; - - if (queue_id == NULL) - { - event.status = osErrorParameter; - return event; - } - - taskWoken = pdFALSE; - - ticks = 0; - if (millisec == osWaitForever) - { - ticks = portMAX_DELAY; - } - else if (millisec != 0) - { - ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) - { - ticks = 1; - } - } - - if (inHandlerMode()) - { - if (xQueueReceiveFromISR(queue_id, &event.value.v, &taskWoken) == pdTRUE) - { - /* We have mail */ - event.status = osEventMessage; - } - else - { - event.status = osOK; - } - portEND_SWITCHING_ISR(taskWoken); - } - else - { - if (xQueueReceive(queue_id, &event.value.v, ticks) == pdTRUE) - { - /* We have mail */ - event.status = osEventMessage; - } - else - { - event.status = (ticks == 0) ? osOK : osEventTimeout; - } - } - - return event; -} - -#endif /* Use Message Queues */ - -/******************** Mail Queue Management Functions ***********************/ -#if (defined(osFeature_MailQ) && (osFeature_MailQ != 0)) /* Use Mail Queues */ - -typedef struct os_mailQ_cb -{ - const osMailQDef_t *queue_def; - QueueHandle_t handle; - osPoolId pool; -} os_mailQ_cb_t; - -/** -* @brief Create and Initialize mail queue -* @param queue_def reference to the mail queue definition obtain with \ref osMailQ -* @param thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL. -* @retval mail queue ID for reference by other functions or NULL in case of error. -* @note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS. -*/ -osMailQId osMailCreate(const osMailQDef_t *queue_def, osThreadId thread_id) -{ -#if (configSUPPORT_DYNAMIC_ALLOCATION == 1) - (void)thread_id; - - osPoolDef_t pool_def = {queue_def->queue_sz, queue_def->item_sz, NULL}; - - /* Create a mail queue control block */ - - *(queue_def->cb) = pvPortMalloc(sizeof(struct os_mailQ_cb)); - - if (*(queue_def->cb) == NULL) - { - return NULL; - } - (*(queue_def->cb))->queue_def = queue_def; - - /* Create a queue in FreeRTOS */ - (*(queue_def->cb))->handle = xQueueCreate(queue_def->queue_sz, sizeof(void *)); - - if ((*(queue_def->cb))->handle == NULL) - { - vPortFree(*(queue_def->cb)); - return NULL; - } - - /* Create a mail pool */ - (*(queue_def->cb))->pool = osPoolCreate(&pool_def); - if ((*(queue_def->cb))->pool == NULL) - { - //TODO: Delete queue. How to do it in FreeRTOS? - vPortFree(*(queue_def->cb)); - return NULL; - } - - return *(queue_def->cb); -#else - return NULL; -#endif -} - -/** -* @brief Allocate a memory block from a mail -* @param queue_id mail queue ID obtained with \ref osMailCreate. -* @param millisec timeout value or 0 in case of no time-out. -* @retval pointer to memory block that can be filled with mail or NULL in case error. -* @note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS. -*/ -void *osMailAlloc(osMailQId queue_id, uint32_t millisec) -{ - (void)millisec; - void *p; - - if (queue_id == NULL) - { - return NULL; - } - - p = osPoolAlloc(queue_id->pool); - - return p; -} - -/** -* @brief Allocate a memory block from a mail and set memory block to zero -* @param queue_id mail queue ID obtained with \ref osMailCreate. -* @param millisec timeout value or 0 in case of no time-out. -* @retval pointer to memory block that can be filled with mail or NULL in case error. -* @note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS. -*/ -void *osMailCAlloc(osMailQId queue_id, uint32_t millisec) -{ - uint32_t i; - void *p = osMailAlloc(queue_id, millisec); - - if (p) - { - for (i = 0; i < queue_id->queue_def->item_sz; i++) - { - ((uint8_t *)p)[i] = 0; - } - } - - return p; -} - -/** -* @brief Put a mail to a queue -* @param queue_id mail queue ID obtained with \ref osMailCreate. -* @param mail memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS. -*/ -osStatus osMailPut(osMailQId queue_id, void *mail) -{ - portBASE_TYPE taskWoken; - - if (queue_id == NULL) - { - return osErrorParameter; - } - - taskWoken = pdFALSE; - - if (inHandlerMode()) - { - if (xQueueSendFromISR(queue_id->handle, &mail, &taskWoken) != pdTRUE) - { - return osErrorOS; - } - portEND_SWITCHING_ISR(taskWoken); - } - else - { - if (xQueueSend(queue_id->handle, &mail, 0) != pdTRUE) - { - return osErrorOS; - } - } - - return osOK; -} - -/** -* @brief Get a mail from a queue -* @param queue_id mail queue ID obtained with \ref osMailCreate. -* @param millisec timeout value or 0 in case of no time-out -* @retval event that contains mail information or error code. -* @note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS. -*/ -osEvent osMailGet(osMailQId queue_id, uint32_t millisec) -{ - portBASE_TYPE taskWoken; - TickType_t ticks; - osEvent event; - - event.def.mail_id = queue_id; - - if (queue_id == NULL) - { - event.status = osErrorParameter; - return event; - } - - taskWoken = pdFALSE; - - ticks = 0; - if (millisec == osWaitForever) - { - ticks = portMAX_DELAY; - } - else if (millisec != 0) - { - ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) - { - ticks = 1; - } - } - - if (inHandlerMode()) - { - if (xQueueReceiveFromISR(queue_id->handle, &event.value.p, &taskWoken) == pdTRUE) - { - /* We have mail */ - event.status = osEventMail; - } - else - { - event.status = osOK; - } - portEND_SWITCHING_ISR(taskWoken); - } - else - { - if (xQueueReceive(queue_id->handle, &event.value.p, ticks) == pdTRUE) - { - /* We have mail */ - event.status = osEventMail; - } - else - { - event.status = (ticks == 0) ? osOK : osEventTimeout; - } - } - - return event; -} - -/** -* @brief Free a memory block from a mail -* @param queue_id mail queue ID obtained with \ref osMailCreate. -* @param mail pointer to the memory block that was obtained with \ref osMailGet. -* @retval status code that indicates the execution status of the function. -* @note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS. -*/ -osStatus osMailFree(osMailQId queue_id, void *mail) -{ - if (queue_id == NULL) - { - return osErrorParameter; - } - - return osPoolFree(queue_id->pool, mail); -} -#endif /* Use Mail Queues */ - -/*************************** Additional specific APIs to Free RTOS ************/ -/** -* @brief Handles the tick increment -* @param none. -* @retval none. -*/ -void osSystickHandler(void) -{ - -#if (INCLUDE_xTaskGetSchedulerState == 1) - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) - { -#endif /* INCLUDE_xTaskGetSchedulerState */ - xPortSysTickHandler(); -#if (INCLUDE_xTaskGetSchedulerState == 1) - } -#endif /* INCLUDE_xTaskGetSchedulerState */ -} - -#if (INCLUDE_eTaskGetState == 1) -/** -* @brief Obtain the state of any thread. -* @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. -* @retval the stae of the thread, states are encoded by the osThreadState enumerated type. -*/ -osThreadState osThreadGetState(osThreadId thread_id) -{ - eTaskState ThreadState; - osThreadState result; - - ThreadState = eTaskGetState(thread_id); - - switch (ThreadState) - { - case eRunning: - result = osThreadRunning; - break; - case eReady: - result = osThreadReady; - break; - case eBlocked: - result = osThreadBlocked; - break; - case eSuspended: - result = osThreadSuspended; - break; - case eDeleted: - result = osThreadDeleted; - break; - default: - result = osThreadError; - } - - return result; -} -#endif /* INCLUDE_eTaskGetState */ - -#if (INCLUDE_eTaskGetState == 1) -/** -* @brief Check if a thread is already suspended or not. -* @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. -* @retval status code that indicates the execution status of the function. -*/ -osStatus osThreadIsSuspended(osThreadId thread_id) -{ - if (eTaskGetState(thread_id) == eSuspended) - return osOK; - else - return osErrorOS; -} -#endif /* INCLUDE_eTaskGetState */ -/** -* @brief Suspend execution of a thread. -* @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. -* @retval status code that indicates the execution status of the function. -*/ -osStatus osThreadSuspend(osThreadId thread_id) -{ -#if (INCLUDE_vTaskSuspend == 1) - vTaskSuspend(thread_id); - - return osOK; -#else - return osErrorResource; -#endif -} - -/** -* @brief Resume execution of a suspended thread. -* @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. -* @retval status code that indicates the execution status of the function. -*/ -osStatus osThreadResume(osThreadId thread_id) -{ -#if (INCLUDE_vTaskSuspend == 1) - if (inHandlerMode()) - { - if (xTaskResumeFromISR(thread_id) == pdTRUE) - { - portYIELD_FROM_ISR(pdTRUE); - } - } - else - { - vTaskResume(thread_id); - } - return osOK; -#else - return osErrorResource; -#endif -} - -/** -* @brief Suspend execution of a all active threads. -* @retval status code that indicates the execution status of the function. -*/ -osStatus osThreadSuspendAll(void) -{ - vTaskSuspendAll(); - - return osOK; -} - -/** -* @brief Resume execution of a all suspended threads. -* @retval status code that indicates the execution status of the function. -*/ -osStatus osThreadResumeAll(void) -{ - if (xTaskResumeAll() == pdTRUE) - return osOK; - else - return osErrorOS; -} - -/** -* @brief Delay a task until a specified time -* @param PreviousWakeTime Pointer to a variable that holds the time at which the -* task was last unblocked. PreviousWakeTime must be initialised with the current time -* prior to its first use (PreviousWakeTime = osKernelSysTick() ) -* @param millisec time delay value -* @retval status code that indicates the execution status of the function. -*/ -osStatus osDelayUntil(uint32_t *PreviousWakeTime, uint32_t millisec) -{ -#if INCLUDE_vTaskDelayUntil - TickType_t ticks = (millisec / portTICK_PERIOD_MS); - vTaskDelayUntil((TickType_t *)PreviousWakeTime, ticks ? ticks : 1); - - return osOK; -#else - (void)millisec; - (void)PreviousWakeTime; - - return osErrorResource; -#endif -} - -/** -* @brief Abort the delay for a specific thread -* @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId -* @retval status code that indicates the execution status of the function. -*/ -osStatus osAbortDelay(osThreadId thread_id) -{ -#if INCLUDE_xTaskAbortDelay - - xTaskAbortDelay(thread_id); - - return osOK; -#else - (void)thread_id; - - return osErrorResource; -#endif -} - -/** -* @brief Lists all the current threads, along with their current state -* and stack usage high water mark. -* @param buffer A buffer into which the above mentioned details -* will be written -* @retval status code that indicates the execution status of the function. -*/ -osStatus osThreadList(uint8_t *buffer) -{ -#if ((configUSE_TRACE_FACILITY == 1) && (configUSE_STATS_FORMATTING_FUNCTIONS == 1)) - vTaskList((char *)buffer); -#endif - return osOK; -} - -/** -* @brief Receive an item from a queue without removing the item from the queue. -* @param queue_id message queue ID obtained with \ref osMessageCreate. -* @param millisec timeout value or 0 in case of no time-out. -* @retval event information that includes status code. -*/ -osEvent osMessagePeek(osMessageQId queue_id, uint32_t millisec) -{ - TickType_t ticks; - osEvent event; - - event.def.message_id = queue_id; - - if (queue_id == NULL) - { - event.status = osErrorParameter; - return event; - } - - ticks = 0; - if (millisec == osWaitForever) - { - ticks = portMAX_DELAY; - } - else if (millisec != 0) - { - ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) - { - ticks = 1; - } - } - - if (xQueuePeek(queue_id, &event.value.v, ticks) == pdTRUE) - { - /* We have mail */ - event.status = osEventMessage; - } - else - { - event.status = (ticks == 0) ? osOK : osEventTimeout; - } - - return event; -} - -/** -* @brief Get the number of messaged stored in a queue. -* @param queue_id message queue ID obtained with \ref osMessageCreate. -* @retval number of messages stored in a queue. -*/ -uint32_t osMessageWaiting(osMessageQId queue_id) -{ - if (inHandlerMode()) - { - return uxQueueMessagesWaitingFromISR(queue_id); - } - else - { - return uxQueueMessagesWaiting(queue_id); - } -} - -/** -* @brief Get the available space in a message queue. -* @param queue_id message queue ID obtained with \ref osMessageCreate. -* @retval available space in a message queue. -*/ -uint32_t osMessageAvailableSpace(osMessageQId queue_id) -{ - return uxQueueSpacesAvailable(queue_id); -} - -/** -* @brief Delete a Message Queue -* @param queue_id message queue ID obtained with \ref osMessageCreate. -* @retval status code that indicates the execution status of the function. -*/ -osStatus osMessageDelete(osMessageQId queue_id) -{ - if (inHandlerMode()) - { - return osErrorISR; - } - - vQueueDelete(queue_id); - - return osOK; -} - -/** -* @brief Create and Initialize a Recursive Mutex -* @param mutex_def mutex definition referenced with \ref osMutex. -* @retval mutex ID for reference by other functions or NULL in case of error.. -*/ -osMutexId osRecursiveMutexCreate(const osMutexDef_t *mutex_def) -{ -#if (configUSE_RECURSIVE_MUTEXES == 1) -#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) - - if (mutex_def->controlblock != NULL) - { - return xSemaphoreCreateRecursiveMutexStatic(mutex_def->controlblock); - } - else - { - return xSemaphoreCreateRecursiveMutex(); - } -#elif (configSUPPORT_STATIC_ALLOCATION == 1) - return xSemaphoreCreateRecursiveMutexStatic(mutex_def->controlblock); -#else - return xSemaphoreCreateRecursiveMutex(); -#endif -#else - return NULL; -#endif -} - -/** -* @brief Release a Recursive Mutex -* @param mutex_id mutex ID obtained by \ref osRecursiveMutexCreate. -* @retval status code that indicates the execution status of the function. -*/ -osStatus osRecursiveMutexRelease(osMutexId mutex_id) -{ -#if (configUSE_RECURSIVE_MUTEXES == 1) - osStatus result = osOK; - - if (xSemaphoreGiveRecursive(mutex_id) != pdTRUE) - { - result = osErrorOS; - } - return result; -#else - return osErrorResource; -#endif -} - -/** -* @brief Release a Recursive Mutex -* @param mutex_id mutex ID obtained by \ref osRecursiveMutexCreate. -* @param millisec timeout value or 0 in case of no time-out. -* @retval status code that indicates the execution status of the function. -*/ -osStatus osRecursiveMutexWait(osMutexId mutex_id, uint32_t millisec) -{ -#if (configUSE_RECURSIVE_MUTEXES == 1) - TickType_t ticks; - - if (mutex_id == NULL) - { - return osErrorParameter; - } - - ticks = 0; - if (millisec == osWaitForever) - { - ticks = portMAX_DELAY; - } - else if (millisec != 0) - { - ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) - { - ticks = 1; - } - } - - if (xSemaphoreTakeRecursive(mutex_id, ticks) != pdTRUE) - { - return osErrorOS; - } - return osOK; -#else - return osErrorResource; -#endif -} - -/** -* @brief Returns the current count value of a counting semaphore -* @param semaphore_id semaphore_id ID obtained by \ref osSemaphoreCreate. -* @retval count value -*/ -uint32_t osSemaphoreGetCount(osSemaphoreId semaphore_id) -{ - return uxSemaphoreGetCount(semaphore_id); -} diff --git a/source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Board/pinecil/Source/GCC/gcc_gd32vf103_flashxip.ld b/source/linkers/gd32vf103.ld similarity index 100% rename from source/Core/BSP/Pine64/Vendor/SoC/gd32vf103/Board/pinecil/Source/GCC/gcc_gd32vf103_flashxip.ld rename to source/linkers/gd32vf103.ld diff --git a/source/Core/BSP/Miniware/stm32f103.ld b/source/linkers/stm32f103.ld similarity index 100% rename from source/Core/BSP/Miniware/stm32f103.ld rename to source/linkers/stm32f103.ld