First impressions since years made on embedded programming with freertos on pico
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
build
|
||||||
|
.vscode/*
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Generated Cmake Pico project file
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
# Initialise pico_sdk from installed location
|
||||||
|
# (note this can come from environment, CMake cache etc)
|
||||||
|
|
||||||
|
# == DO NOT EDIT THE FOLLOWING LINES for the Raspberry Pi Pico VS Code Extension to work ==
|
||||||
|
if(WIN32)
|
||||||
|
set(USERHOME $ENV{USERPROFILE})
|
||||||
|
else()
|
||||||
|
set(USERHOME $ENV{HOME})
|
||||||
|
endif()
|
||||||
|
set(sdkVersion 2.2.0)
|
||||||
|
set(toolchainVersion RISCV_ZCB_RPI_2_2_0_3)
|
||||||
|
set(picotoolVersion 2.2.0-a4)
|
||||||
|
set(picoVscode ${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake)
|
||||||
|
if (EXISTS ${picoVscode})
|
||||||
|
include(${picoVscode})
|
||||||
|
endif()
|
||||||
|
# ====================================================================================
|
||||||
|
set(PICO_BOARD pico2 CACHE STRING "Board type")
|
||||||
|
|
||||||
|
# Pull in Raspberry Pi Pico SDK (must be before project)
|
||||||
|
include(pico_sdk_import.cmake)
|
||||||
|
|
||||||
|
project(PicoSDKandFreeRtos C CXX ASM)
|
||||||
|
|
||||||
|
# Initialise the Raspberry Pi Pico SDK
|
||||||
|
pico_sdk_init()
|
||||||
|
|
||||||
|
set(FREERTOS_KERNEL_PATH "${CMAKE_CURRENT_LIST_DIR}/FreeRTOS")
|
||||||
|
set(FREERTOS_CONFIG_FILE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}")
|
||||||
|
include(${FREERTOS_KERNEL_PATH}/portable/ThirdParty/GCC/RP2040/FreeRTOS_Kernel_import.cmake)
|
||||||
|
|
||||||
|
# Add executable. Default name is the project name, version 0.1
|
||||||
|
|
||||||
|
add_executable(PicoSDKandFreeRtos main.cpp )
|
||||||
|
|
||||||
|
pico_set_program_name(PicoSDKandFreeRtos "PicoSDKandFreeRtos")
|
||||||
|
pico_set_program_version(PicoSDKandFreeRtos "0.1")
|
||||||
|
|
||||||
|
# Modify the below lines to enable/disable output over UART/USB
|
||||||
|
pico_enable_stdio_uart(PicoSDKandFreeRtos 0)
|
||||||
|
pico_enable_stdio_usb(PicoSDKandFreeRtos 1)
|
||||||
|
|
||||||
|
# Add the standard library to the build
|
||||||
|
target_link_libraries(PicoSDKandFreeRtos
|
||||||
|
pico_stdlib
|
||||||
|
FreeRTOS-Kernel-Heap4)
|
||||||
|
|
||||||
|
# Add the standard include files to the build
|
||||||
|
target_include_directories(PicoSDKandFreeRtos PRIVATE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
pico_add_extra_outputs(PicoSDKandFreeRtos)
|
||||||
@@ -0,0 +1,289 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
|
# User is responsible to one mandatory option:
|
||||||
|
# FREERTOS_PORT, if not specified and native port detected, uses the native compile.
|
||||||
|
#
|
||||||
|
# User is responsible for one library target:
|
||||||
|
# freertos_config ,typically an INTERFACE library
|
||||||
|
#
|
||||||
|
# DEPRECATED: FREERTOS_CONFIG_FILE_DIRECTORY - but still supported if no freertos_config defined for now.
|
||||||
|
# May be removed at some point in the future.
|
||||||
|
#
|
||||||
|
# User can choose which heap implementation to use (either the implementations
|
||||||
|
# included with FreeRTOS [1..5] or a custom implementation) by providing the
|
||||||
|
# option FREERTOS_HEAP. When dynamic allocation is used, the user must specify a
|
||||||
|
# heap implementation. If the option is not set, the cmake will use no heap
|
||||||
|
# implementation (e.g. when only static allocation is used).
|
||||||
|
|
||||||
|
# `freertos_config` target defines the path to FreeRTOSConfig.h and optionally other freertos based config files
|
||||||
|
if(NOT TARGET freertos_config )
|
||||||
|
if (NOT DEFINED FREERTOS_CONFIG_FILE_DIRECTORY )
|
||||||
|
|
||||||
|
message(FATAL_ERROR " freertos_config target not specified. Please specify a cmake target that defines the include directory for FreeRTOSConfig.h:\n"
|
||||||
|
" add_library(freertos_config INTERFACE)\n"
|
||||||
|
" target_include_directories(freertos_config SYSTEM\n"
|
||||||
|
" INTERFACE\n"
|
||||||
|
" include) # The config file directory\n"
|
||||||
|
" target_compile_definitions(freertos_config\n"
|
||||||
|
" PUBLIC\n"
|
||||||
|
" projCOVERAGE_TEST=0)\n")
|
||||||
|
else()
|
||||||
|
message(WARNING " Using deprecated 'FREERTOS_CONFIG_FILE_DIRECTORY' - please update your project CMakeLists.txt file:\n"
|
||||||
|
" add_library(freertos_config INTERFACE)\n"
|
||||||
|
" target_include_directories(freertos_config SYSTEM\n"
|
||||||
|
" INTERFACE\n"
|
||||||
|
" include) # The config file directory\n"
|
||||||
|
" target_compile_definitions(freertos_config\n"
|
||||||
|
" PUBLIC\n"
|
||||||
|
" projCOVERAGE_TEST=0)\n")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# FreeRTOS port option
|
||||||
|
if(NOT FREERTOS_PORT)
|
||||||
|
message(WARNING " FREERTOS_PORT is not set. Please specify it from top-level CMake file (example):\n"
|
||||||
|
" set(FREERTOS_PORT GCC_ARM_CM4F CACHE STRING \"\")\n"
|
||||||
|
" or from CMake command line option:\n"
|
||||||
|
" -DFREERTOS_PORT=GCC_ARM_CM4F\n"
|
||||||
|
" \n"
|
||||||
|
" Available port options:\n"
|
||||||
|
" A_CUSTOM_PORT - Compiler: User Defined Target: User Defined\n"
|
||||||
|
" BCC_16BIT_DOS_FLSH186 - Compiler: BCC Target: 16 bit DOS Flsh186\n"
|
||||||
|
" BCC_16BIT_DOS_PC - Compiler: BCC Target: 16 bit DOS PC\n"
|
||||||
|
" CCS_ARM_CM3 - Compiler: CCS Target: ARM Cortex-M3\n"
|
||||||
|
" CCS_ARM_CM4F - Compiler: CCS Target: ARM Cortex-M4 with FPU\n"
|
||||||
|
" CCS_ARM_CR4 - Compiler: CCS Target: ARM Cortex-R4\n"
|
||||||
|
" CCS_MSP430X - Compiler: CCS Target: MSP430X\n"
|
||||||
|
" CODEWARRIOR_COLDFIRE_V1 - Compiler: CoreWarrior Target: ColdFire V1\n"
|
||||||
|
" CODEWARRIOR_COLDFIRE_V2 - Compiler: CoreWarrior Target: ColdFire V2\n"
|
||||||
|
" CODEWARRIOR_HCS12 - Compiler: CoreWarrior Target: HCS12\n"
|
||||||
|
" GCC_ARM_CA9 - Compiler: GCC Target: ARM Cortex-A9\n"
|
||||||
|
" GCC_ARM_AARCH64 - Compiler: GCC Target: ARM v8-A\n"
|
||||||
|
" GCC_ARM_AARCH64_SRE - Compiler: GCC Target: ARM v8-A SRE\n"
|
||||||
|
" GCC_ARM_CM0 - Compiler: GCC Target: ARM Cortex-M0\n"
|
||||||
|
" GCC_ARM_CM3 - Compiler: GCC Target: ARM Cortex-M3\n"
|
||||||
|
" GCC_ARM_CM3_MPU - Compiler: GCC Target: ARM Cortex-M3 with MPU\n"
|
||||||
|
" GCC_ARM_CM4_MPU - Compiler: GCC Target: ARM Cortex-M4 with MPU\n"
|
||||||
|
" GCC_ARM_CM4F - Compiler: GCC Target: ARM Cortex-M4 with FPU\n"
|
||||||
|
" GCC_ARM_CM7 - Compiler: GCC Target: ARM Cortex-M7\n"
|
||||||
|
" GCC_ARM_CM23_NONSECURE - Compiler: GCC Target: ARM Cortex-M23 non-secure\n"
|
||||||
|
" GCC_ARM_CM23_SECURE - Compiler: GCC Target: ARM Cortex-M23 secure\n"
|
||||||
|
" GCC_ARM_CM23_NTZ_NONSECURE - Compiler: GCC Target: ARM Cortex-M23 non-trustzone non-secure\n"
|
||||||
|
" GCC_ARM_CM33_NONSECURE - Compiler: GCC Target: ARM Cortex-M33 non-secure\n"
|
||||||
|
" GCC_ARM_CM33_SECURE - Compiler: GCC Target: ARM Cortex-M33 secure\n"
|
||||||
|
" GCC_ARM_CM33_NTZ_NONSECURE - Compiler: GCC Target: ARM Cortex-M33 non-trustzone non-secure\n"
|
||||||
|
" GCC_ARM_CM33_TFM - Compiler: GCC Target: ARM Cortex-M33 non-secure for TF-M\n"
|
||||||
|
" GCC_ARM_CM35P_NONSECURE - Compiler: GCC Target: ARM Cortex-M35P non-secure\n"
|
||||||
|
" GCC_ARM_CM35P_SECURE - Compiler: GCC Target: ARM Cortex-M35P secure\n"
|
||||||
|
" GCC_ARM_CM35P_NTZ_NONSECURE - Compiler: GCC Target: ARM Cortex-M35P non-trustzone non-secure\n"
|
||||||
|
" GCC_ARM_CM52_NONSECURE - Compiler: GCC Target: ARM Cortex-M52 non-secure\n"
|
||||||
|
" GCC_ARM_CM52_SECURE - Compiler: GCC Target: ARM Cortex-M52 secure\n"
|
||||||
|
" GCC_ARM_CM52_NTZ_NONSECURE - Compiler: GCC Target: ARM Cortex-M52 non-trustzone non-secure\n"
|
||||||
|
" GCC_ARM_CM52_TFM - Compiler: GCC Target: ARM Cortex-M52 non-secure for TF-M\n"
|
||||||
|
" GCC_ARM_CM55_NONSECURE - Compiler: GCC Target: ARM Cortex-M55 non-secure\n"
|
||||||
|
" GCC_ARM_CM55_SECURE - Compiler: GCC Target: ARM Cortex-M55 secure\n"
|
||||||
|
" GCC_ARM_CM55_NTZ_NONSECURE - Compiler: GCC Target: ARM Cortex-M55 non-trustzone non-secure\n"
|
||||||
|
" GCC_ARM_CM55_TFM - Compiler: GCC Target: ARM Cortex-M55 non-secure for TF-M\n"
|
||||||
|
" GCC_ARM_CM85_NONSECURE - Compiler: GCC Target: ARM Cortex-M85 non-secure\n"
|
||||||
|
" GCC_ARM_CM85_SECURE - Compiler: GCC Target: ARM Cortex-M85 secure\n"
|
||||||
|
" GCC_ARM_CM85_NTZ_NONSECURE - Compiler: GCC Target: ARM Cortex-M85 non-trustzone non-secure\n"
|
||||||
|
" GCC_ARM_CM85_TFM - Compiler: GCC Target: ARM Cortex-M85 non-secure for TF-M\n"
|
||||||
|
" GCC_ARM_STAR_MC3_NONSECURE - Compiler: GCC Target: Arm China STAR-MC3 non-secure\n"
|
||||||
|
" GCC_ARM_STAR_MC3_SECURE - Compiler: GCC Target: Arm China STAR-MC3 secure\n"
|
||||||
|
" GCC_ARM_STAR_MC3_NTZ_NONSECURE - Compiler: GCC Target: Arm China STAR-MC3 non-trustzone non-secure\n"
|
||||||
|
" GCC_ARM_STAR_MC3_TFM - Compiler: GCC Target: Arm China STAR-MC3 non-secure for TF-M\n"
|
||||||
|
" GCC_ARM_CR5 - Compiler: GCC Target: ARM Cortex-R5\n"
|
||||||
|
" GCC_ARM_CRX_MPU - Compiler: GCC Target: ARM Cortex-Rx with MPU\n"
|
||||||
|
" GCC_ARM_CRX_NOGIC - Compiler: GCC Target: ARM Cortex-Rx no GIC\n"
|
||||||
|
" GCC_ARM_CR82 - Compiler: GCC Target: ARM Cortex-R82\n"
|
||||||
|
" GCC_ARM7_AT91FR40008 - Compiler: GCC Target: ARM7 Atmel AT91R40008\n"
|
||||||
|
" GCC_ARM7_AT91SAM7S - Compiler: GCC Target: ARM7 Atmel AT91SAM7S\n"
|
||||||
|
" GCC_ARM7_LPC2000 - Compiler: GCC Target: ARM7 LPC2000\n"
|
||||||
|
" GCC_ARM7_LPC23XX - Compiler: GCC Target: ARM7 LPC23xx\n"
|
||||||
|
" GCC_ATMEGA323 - Compiler: GCC Target: ATMega323\n"
|
||||||
|
" GCC_AVR32_UC3 - Compiler: GCC Target: AVR32 UC3\n"
|
||||||
|
" GCC_COLDFIRE_V2 - Compiler: GCC Target: ColdFire V2\n"
|
||||||
|
" GCC_CORTUS_APS3 - Compiler: GCC Target: CORTUS APS3\n"
|
||||||
|
" GCC_H8S2329 - Compiler: GCC Target: H8S2329\n"
|
||||||
|
" GCC_HCS12 - Compiler: GCC Target: HCS12\n"
|
||||||
|
" GCC_IA32_FLAT - Compiler: GCC Target: IA32 flat\n"
|
||||||
|
" GCC_MICROBLAZE - Compiler: GCC Target: MicroBlaze\n"
|
||||||
|
" GCC_MICROBLAZE_V8 - Compiler: GCC Target: MicroBlaze V8\n"
|
||||||
|
" GCC_MICROBLAZE_V9 - Compiler: GCC Target: MicroBlaze V9\n"
|
||||||
|
" GCC_MSP430F449 - Compiler: GCC Target: MSP430F449\n"
|
||||||
|
" GCC_NIOSII - Compiler: GCC Target: NiosII\n"
|
||||||
|
" GCC_PPC405_XILINX - Compiler: GCC Target: Xilinx PPC405\n"
|
||||||
|
" GCC_PPC440_XILINX - Compiler: GCC Target: Xilinx PPC440\n"
|
||||||
|
" GCC_RISC_V - Compiler: GCC Target: RISC-V\n"
|
||||||
|
" GCC_RISC_V_PULPINO_VEGA_RV32M1RM - Compiler: GCC Target: RISC-V Pulpino Vega RV32M1RM\n"
|
||||||
|
" GCC_RISC_V_GENERIC - Compiler: GCC Target: RISC-V with FREERTOS_RISCV_EXTENSION\n"
|
||||||
|
" GCC_RL78 - Compiler: GCC Target: Renesas RL78\n"
|
||||||
|
" GCC_RX100 - Compiler: GCC Target: Renesas RX100\n"
|
||||||
|
" GCC_RX200 - Compiler: GCC Target: Renesas RX200\n"
|
||||||
|
" GCC_RX600 - Compiler: GCC Target: Renesas RX600\n"
|
||||||
|
" GCC_RX600_V2 - Compiler: GCC Target: Renesas RX600 v2\n"
|
||||||
|
" GCC_RX700_V3_DPFPU - Compiler: GCC Target: Renesas RX700 v3 with DPFPU\n"
|
||||||
|
" GCC_STR75X - Compiler: GCC Target: STR75x\n"
|
||||||
|
" GCC_TRICORE_1782 - Compiler: GCC Target: TriCore 1782\n"
|
||||||
|
" GCC_ARC_EM_HS - Compiler: GCC Target: DesignWare ARC EM HS\n"
|
||||||
|
" GCC_ARC_V1 - Compiler: GCC Target: DesignWare ARC v1\n"
|
||||||
|
" GCC_ATMEGA - Compiler: GCC Target: ATmega\n"
|
||||||
|
" GCC_POSIX - Compiler: GCC Target: Posix\n"
|
||||||
|
" GCC_RP2040 - Compiler: GCC Target: RP2040 ARM Cortex-M0+\n"
|
||||||
|
" GCC_XTENSA_ESP32 - Compiler: GCC Target: Xtensa ESP32\n"
|
||||||
|
" GCC_AVRDX - Compiler: GCC Target: AVRDx\n"
|
||||||
|
" GCC_AVR_MEGA0 - Compiler: GCC Target: AVR Mega0\n"
|
||||||
|
" IAR_78K0K - Compiler: IAR Target: Renesas 78K0K\n"
|
||||||
|
" IAR_ARM_CA5_NOGIC - Compiler: IAR Target: ARM Cortex-A5 no GIC\n"
|
||||||
|
" IAR_ARM_CA9 - Compiler: IAR Target: ARM Cortex-A9\n"
|
||||||
|
" IAR_ARM_CM0 - Compiler: IAR Target: ARM Cortex-M0\n"
|
||||||
|
" IAR_ARM_CM3 - Compiler: IAR Target: ARM Cortex-M3\n"
|
||||||
|
" IAR_ARM_CM4F - Compiler: IAR Target: ARM Cortex-M4 with FPU\n"
|
||||||
|
" IAR_ARM_CM4F_MPU - Compiler: IAR Target: ARM Cortex-M4 with FPU and MPU\n"
|
||||||
|
" IAR_ARM_CM7 - Compiler: IAR Target: ARM Cortex-M7\n"
|
||||||
|
" IAR_ARM_CM23_NONSECURE - Compiler: IAR Target: ARM Cortex-M23 non-secure\n"
|
||||||
|
" IAR_ARM_CM23_SECURE - Compiler: IAR Target: ARM Cortex-M23 secure\n"
|
||||||
|
" IAR_ARM_CM23_NTZ_NONSECURE - Compiler: IAR Target: ARM Cortex-M23 non-trustzone non-secure\n"
|
||||||
|
" IAR_ARM_CM33_NONSECURE - Compiler: IAR Target: ARM Cortex-M33 non-secure\n"
|
||||||
|
" IAR_ARM_CM33_SECURE - Compiler: IAR Target: ARM Cortex-M33 secure\n"
|
||||||
|
" IAR_ARM_CM33_NTZ_NONSECURE - Compiler: IAR Target: ARM Cortex-M33 non-trustzone non-secure\n"
|
||||||
|
" IAR_ARM_CM33_TFM - Compiler: IAR Target: ARM Cortex-M33 non-secure for TF-M\n"
|
||||||
|
" IAR_ARM_CM35P_NONSECURE - Compiler: IAR Target: ARM Cortex-M35P non-secure\n"
|
||||||
|
" IAR_ARM_CM35P_SECURE - Compiler: IAR Target: ARM Cortex-M35P secure\n"
|
||||||
|
" IAR_ARM_CM35P_NTZ_NONSECURE - Compiler: IAR Target: ARM Cortex-M35P non-trustzone non-secure\n"
|
||||||
|
" IAR_ARM_CM52_NONSECURE - Compiler: IAR Target: ARM Cortex-M52 non-secure\n"
|
||||||
|
" IAR_ARM_CM52_SECURE - Compiler: IAR Target: ARM Cortex-M52 secure\n"
|
||||||
|
" IAR_ARM_CM52_NTZ_NONSECURE - Compiler: IAR Target: ARM Cortex-M52 non-trustzone non-secure\n"
|
||||||
|
" IAR_ARM_CM52_TFM - Compiler: IAR Target: ARM Cortex-M52 non-secure for TF-M\n"
|
||||||
|
" IAR_ARM_CM55_NONSECURE - Compiler: IAR Target: ARM Cortex-M55 non-secure\n"
|
||||||
|
" IAR_ARM_CM55_SECURE - Compiler: IAR Target: ARM Cortex-M55 secure\n"
|
||||||
|
" IAR_ARM_CM55_NTZ_NONSECURE - Compiler: IAR Target: ARM Cortex-M55 non-trustzone non-secure\n"
|
||||||
|
" IAR_ARM_CM55_TFM - Compiler: IAR Target: ARM Cortex-M55 non-secure for TF-M\n"
|
||||||
|
" IAR_ARM_CM85_NONSECURE - Compiler: IAR Target: ARM Cortex-M85 non-secure\n"
|
||||||
|
" IAR_ARM_CM85_SECURE - Compiler: IAR Target: ARM Cortex-M85 secure\n"
|
||||||
|
" IAR_ARM_CM85_NTZ_NONSECURE - Compiler: IAR Target: ARM Cortex-M85 non-trustzone non-secure\n"
|
||||||
|
" IAR_ARM_CM85_TFM - Compiler: IAR Target: ARM Cortex-M85 non-secure for TF-M\n"
|
||||||
|
" IAR_ARM_STAR_MC3_NONSECURE - Compiler: IAR Target: Arm China STAR-MC3 non-secure\n"
|
||||||
|
" IAR_ARM_STAR_MC3_SECURE - Compiler: IAR Target: Arm China STAR-MC3 secure\n"
|
||||||
|
" IAR_ARM_STAR_MC3_NTZ_NONSECURE - Compiler: IAR Target: Arm China STAR-MC3 non-trustzone non-secure\n"
|
||||||
|
" IAR_ARM_STAR_MC3_TFM - Compiler: IAR Target: Arm China STAR-MC3 non-secure for TF-M\n"
|
||||||
|
" IAR_ARM_CRX_NOGIC - Compiler: IAR Target: ARM Cortex-Rx no GIC\n"
|
||||||
|
" IAR_ATMEGA323 - Compiler: IAR Target: ATMega323\n"
|
||||||
|
" IAR_ATMEL_SAM7S64 - Compiler: IAR Target: Atmel SAM7S64\n"
|
||||||
|
" IAR_ATMEL_SAM9XE - Compiler: IAR Target: Atmel SAM9XE\n"
|
||||||
|
" IAR_AVR_AVRDX - Compiler: IAR Target: AVRDx\n"
|
||||||
|
" IAR_AVR_MEGA0 - Compiler: IAR Target: AVR Mega0\n"
|
||||||
|
" IAR_AVR32_UC3 - Compiler: IAR Target: AVR32 UC3\n"
|
||||||
|
" IAR_LPC2000 - Compiler: IAR Target: LPC2000\n"
|
||||||
|
" IAR_MSP430 - Compiler: IAR Target: MSP430\n"
|
||||||
|
" IAR_MSP430X - Compiler: IAR Target: MSP430X\n"
|
||||||
|
" IAR_RISC_V - Compiler: IAR Target: RISC-V\n"
|
||||||
|
" IAR_RISC_V_GENERIC - Compiler: IAR Target: RISC-V with FREERTOS_RISCV_EXTENSION\n"
|
||||||
|
" IAR_RL78 - Compiler: IAR Target: Renesas RL78\n"
|
||||||
|
" IAR_RX100 - Compiler: IAR Target: Renesas RX100\n"
|
||||||
|
" IAR_RX600 - Compiler: IAR Target: Renesas RX600\n"
|
||||||
|
" IAR_RX700_V3_DPFPU - Compiler: IAR Target: Renesas RX700 v3 with DPFPU\n"
|
||||||
|
" IAR_RX_V2 - Compiler: IAR Target: Renesas RX v2\n"
|
||||||
|
" IAR_STR71X - Compiler: IAR Target: STR71x\n"
|
||||||
|
" IAR_STR75X - Compiler: IAR Target: STR75x\n"
|
||||||
|
" IAR_STR91X - Compiler: IAR Target: STR91x\n"
|
||||||
|
" IAR_V850ES_FX3 - Compiler: IAR Target: Renesas V850ES/Fx3\n"
|
||||||
|
" IAR_V850ES_HX3 - Compiler: IAR Target: Renesas V850ES/Hx3\n"
|
||||||
|
" MIKROC_ARM_CM4F - Compiler: MikroC Target: ARM Cortex-M4 with FPU\n"
|
||||||
|
" MPLAB_PIC18F - Compiler: MPLAB Target: PIC18F\n"
|
||||||
|
" MPLAB_PIC24 - Compiler: MPLAB Target: PIC24\n"
|
||||||
|
" MPLAB_PIC32MEC14XX - Compiler: MPLAB Target: PIC32MEC14xx\n"
|
||||||
|
" MPLAB_PIC32MX - Compiler: MPLAB Target: PIC32MX\n"
|
||||||
|
" MPLAB_PIC32MZ - Compiler: MPLAB Target: PIC32MZ\n"
|
||||||
|
" MSVC_MINGW - Compiler: MSVC or MinGW Target: x86\n"
|
||||||
|
" OWATCOM_16BIT_DOS_FLSH186 - Compiler: Open Watcom Target: 16 bit DOS Flsh186\n"
|
||||||
|
" OWATCOM_16BIT_DOS_PC - Compiler: Open Watcom Target: 16 bit DOS PC\n"
|
||||||
|
" PARADIGM_TERN_EE_LARGE - Compiler: Paradigm Target: Tern EE large\n"
|
||||||
|
" PARADIGM_TERN_EE_SMALL - Compiler: Paradigm Target: Tern EE small\n"
|
||||||
|
" RENESAS_RX100 - Compiler: Renesas Target: RX100\n"
|
||||||
|
" RENESAS_RX200 - Compiler: Renesas Target: RX200\n"
|
||||||
|
" RENESAS_RX600 - Compiler: Renesas Target: RX600\n"
|
||||||
|
" RENESAS_RX600_V2 - Compiler: Renesas Target: RX600 v2\n"
|
||||||
|
" RENESAS_RX700_V3_DPFPU - Compiler: Renesas Target: RX700 v3 with DPFPU\n"
|
||||||
|
" RENESAS_SH2A_FPU - Compiler: Renesas Target: SH2A with FPU\n"
|
||||||
|
" ROWLEY_MSP430F449 - Compiler: Rowley Target: MSP430F449\n"
|
||||||
|
" RVDS_ARM_CA9 - Compiler: RVDS Target: ARM Cortex-A9\n"
|
||||||
|
" RVDS_ARM_CM0 - Compiler: RVDS Target: ARM Cortex-M0\n"
|
||||||
|
" RVDS_ARM_CM3 - Compiler: RVDS Target: ARM Cortex-M3\n"
|
||||||
|
" RVDS_ARM_CM4_MPU - Compiler: RVDS Target: ARM Cortex-M4 with MPU\n"
|
||||||
|
" RVDS_ARM_CM4F - Compiler: RVDS Target: ARM Cortex-M4 with FPU\n"
|
||||||
|
" RVDS_ARM_CM7 - Compiler: RVDS Target: ARM Cortex-M7\n"
|
||||||
|
" RVDS_ARM7_LPC21XX - Compiler: RVDS Target: ARM7 LPC21xx\n"
|
||||||
|
" SDCC_CYGNAL - Compiler: SDCC Target: Cygnal\n"
|
||||||
|
" SOFTUNE_MB91460 - Compiler: Softune Target: MB91460\n"
|
||||||
|
" SOFTUNE_MB96340 - Compiler: Softune Target: MB96340\n"
|
||||||
|
" TASKING_ARM_CM4F - Compiler: Tasking Target: ARM Cortex-M4 with FPU\n"
|
||||||
|
" TEMPLATE - Compiler: HOST Target: None\n"
|
||||||
|
" CDK_THEAD_CK802 - Compiler: CDK Target: T-head CK802\n"
|
||||||
|
" XCC_XTENSA - Compiler: XCC Target: Xtensa\n"
|
||||||
|
" WIZC_PIC18 - Compiler: WizC Target: PIC18")
|
||||||
|
# Native FREERTOS_PORT for Linux and Windows MINGW builds
|
||||||
|
if(UNIX)
|
||||||
|
message(STATUS " Auto-Detected Unix, setting FREERTOS_PORT=GCC_POSIX")
|
||||||
|
set(FREERTOS_PORT GCC_POSIX CACHE STRING "FreeRTOS port name")
|
||||||
|
elseif(MINGW)
|
||||||
|
message(STATUS " Auto-Detected MINGW, setting FREERTOS_PORT=MSVC_MINGW")
|
||||||
|
set(FREERTOS_PORT MSVC_MINGW CACHE STRING "FreeRTOS port name")
|
||||||
|
endif()
|
||||||
|
elseif((FREERTOS_PORT STREQUAL "A_CUSTOM_PORT") AND (NOT TARGET freertos_kernel_port) )
|
||||||
|
message(FATAL_ERROR " FREERTOS_PORT is set to A_CUSTOM_PORT. Please specify the custom port target with all necessary files. For example:\n"
|
||||||
|
" Assuming a directory of:\n"
|
||||||
|
" FreeRTOSCustomPort/\n"
|
||||||
|
" CMakeLists.txt\n"
|
||||||
|
" port.c\n"
|
||||||
|
" portmacro.h\n"
|
||||||
|
" Where FreeRTOSCustomPort/CMakeLists.txt is a modified version of:\n"
|
||||||
|
" add_library(freertos_kernel_port OBJECT)\n"
|
||||||
|
" target_sources(freertos_kernel_port\n"
|
||||||
|
" PRIVATE\n"
|
||||||
|
" port.c\n"
|
||||||
|
" portmacro.h)\n"
|
||||||
|
" add_library(freertos_kernel_port_headers INTERFACE)\n"
|
||||||
|
" target_include_directories(freertos_kernel_port_headers INTERFACE \n"
|
||||||
|
" .)\n"
|
||||||
|
" target_link_libraries(freertos_kernel_port\n"
|
||||||
|
" PRIVATE\n"
|
||||||
|
" freertos_kernel_port_headers\n"
|
||||||
|
" freertos_kernel_include)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(freertos_kernel STATIC)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
add_subdirectory(include)
|
||||||
|
add_subdirectory(portable)
|
||||||
|
|
||||||
|
target_sources(freertos_kernel PRIVATE
|
||||||
|
croutine.c
|
||||||
|
event_groups.c
|
||||||
|
list.c
|
||||||
|
queue.c
|
||||||
|
stream_buffer.c
|
||||||
|
tasks.c
|
||||||
|
timers.c
|
||||||
|
)
|
||||||
|
|
||||||
|
if (DEFINED FREERTOS_HEAP )
|
||||||
|
# User specified a heap implementation add heap implementation to freertos_kernel.
|
||||||
|
target_sources(freertos_kernel PRIVATE
|
||||||
|
# If FREERTOS_HEAP is digit between 1 .. 5 - it is heap number, otherwise - it is path to custom heap source file
|
||||||
|
$<IF:$<BOOL:$<FILTER:${FREERTOS_HEAP},EXCLUDE,^[1-5]$>>,${FREERTOS_HEAP},portable/MemMang/heap_${FREERTOS_HEAP}.c>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
target_link_libraries(freertos_kernel
|
||||||
|
PUBLIC
|
||||||
|
freertos_kernel_include
|
||||||
|
freertos_kernel_port_headers
|
||||||
|
PRIVATE
|
||||||
|
freertos_kernel_port
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
@@ -0,0 +1,405 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "croutine.h"
|
||||||
|
|
||||||
|
/* Remove the whole file if co-routines are not being used. */
|
||||||
|
#if ( configUSE_CO_ROUTINES != 0 )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some kernel aware debuggers require data to be viewed to be global, rather
|
||||||
|
* than file scope.
|
||||||
|
*/
|
||||||
|
#ifdef portREMOVE_STATIC_QUALIFIER
|
||||||
|
#define static
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Lists for ready and blocked co-routines. --------------------*/
|
||||||
|
static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /**< Prioritised ready co-routines. */
|
||||||
|
static List_t xDelayedCoRoutineList1; /**< Delayed co-routines. */
|
||||||
|
static List_t xDelayedCoRoutineList2; /**< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
|
||||||
|
static List_t * pxDelayedCoRoutineList = NULL; /**< Points to the delayed co-routine list currently being used. */
|
||||||
|
static List_t * pxOverflowDelayedCoRoutineList = NULL; /**< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
|
||||||
|
static List_t xPendingReadyCoRoutineList; /**< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
|
||||||
|
|
||||||
|
/* Other file private variables. --------------------------------*/
|
||||||
|
CRCB_t * pxCurrentCoRoutine = NULL;
|
||||||
|
static UBaseType_t uxTopCoRoutineReadyPriority = ( UBaseType_t ) 0U;
|
||||||
|
static TickType_t xCoRoutineTickCount = ( TickType_t ) 0U;
|
||||||
|
static TickType_t xLastTickCount = ( TickType_t ) 0U;
|
||||||
|
static TickType_t xPassedTicks = ( TickType_t ) 0U;
|
||||||
|
|
||||||
|
/* The initial state of the co-routine when it is created. */
|
||||||
|
#define corINITIAL_STATE ( 0 )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Place the co-routine represented by pxCRCB into the appropriate ready queue
|
||||||
|
* for the priority. It is inserted at the end of the list.
|
||||||
|
*
|
||||||
|
* This macro accesses the co-routine ready lists and therefore must not be
|
||||||
|
* used from within an ISR.
|
||||||
|
*/
|
||||||
|
#define prvAddCoRoutineToReadyQueue( pxCRCB ) \
|
||||||
|
do { \
|
||||||
|
if( ( pxCRCB )->uxPriority > uxTopCoRoutineReadyPriority ) \
|
||||||
|
{ \
|
||||||
|
uxTopCoRoutineReadyPriority = ( pxCRCB )->uxPriority; \
|
||||||
|
} \
|
||||||
|
vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ ( pxCRCB )->uxPriority ] ), &( ( pxCRCB )->xGenericListItem ) ); \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility to ready all the lists used by the scheduler. This is called
|
||||||
|
* automatically upon the creation of the first co-routine.
|
||||||
|
*/
|
||||||
|
static void prvInitialiseCoRoutineLists( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Co-routines that are readied by an interrupt cannot be placed directly into
|
||||||
|
* the ready lists (there is no mutual exclusion). Instead they are placed in
|
||||||
|
* in the pending ready list in order that they can later be moved to the ready
|
||||||
|
* list by the co-routine scheduler.
|
||||||
|
*/
|
||||||
|
static void prvCheckPendingReadyList( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro that looks at the list of co-routines that are currently delayed to
|
||||||
|
* see if any require waking.
|
||||||
|
*
|
||||||
|
* Co-routines are stored in the queue in the order of their wake time -
|
||||||
|
* meaning once one co-routine has been found whose timer has not expired
|
||||||
|
* we need not look any further down the list.
|
||||||
|
*/
|
||||||
|
static void prvCheckDelayedList( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
UBaseType_t uxIndex )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
CRCB_t * pxCoRoutine;
|
||||||
|
|
||||||
|
traceENTER_xCoRoutineCreate( pxCoRoutineCode, uxPriority, uxIndex );
|
||||||
|
|
||||||
|
/* Allocate the memory that will store the co-routine control block. */
|
||||||
|
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
|
||||||
|
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||||
|
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||||
|
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
|
||||||
|
|
||||||
|
if( pxCoRoutine )
|
||||||
|
{
|
||||||
|
/* If pxCurrentCoRoutine is NULL then this is the first co-routine to
|
||||||
|
* be created and the co-routine data structures need initialising. */
|
||||||
|
if( pxCurrentCoRoutine == NULL )
|
||||||
|
{
|
||||||
|
pxCurrentCoRoutine = pxCoRoutine;
|
||||||
|
prvInitialiseCoRoutineLists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the priority is within limits. */
|
||||||
|
if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
|
||||||
|
{
|
||||||
|
uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill out the co-routine control block from the function parameters. */
|
||||||
|
pxCoRoutine->uxState = corINITIAL_STATE;
|
||||||
|
pxCoRoutine->uxPriority = uxPriority;
|
||||||
|
pxCoRoutine->uxIndex = uxIndex;
|
||||||
|
pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
|
||||||
|
|
||||||
|
/* Initialise all the other co-routine control block parameters. */
|
||||||
|
vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
|
||||||
|
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
|
||||||
|
|
||||||
|
/* Set the co-routine control block as a link back from the ListItem_t.
|
||||||
|
* This is so we can get back to the containing CRCB from a generic item
|
||||||
|
* in a list. */
|
||||||
|
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
|
||||||
|
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
|
||||||
|
|
||||||
|
/* Event lists are always in priority order. */
|
||||||
|
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
|
||||||
|
|
||||||
|
/* Now the co-routine has been initialised it can be added to the ready
|
||||||
|
* list at the correct priority. */
|
||||||
|
prvAddCoRoutineToReadyQueue( pxCoRoutine );
|
||||||
|
|
||||||
|
xReturn = pdPASS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
traceRETURN_xCoRoutineCreate( xReturn );
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
|
||||||
|
List_t * pxEventList )
|
||||||
|
{
|
||||||
|
TickType_t xTimeToWake;
|
||||||
|
|
||||||
|
traceENTER_vCoRoutineAddToDelayedList( xTicksToDelay, pxEventList );
|
||||||
|
|
||||||
|
/* Calculate the time to wake - this may overflow but this is
|
||||||
|
* not a problem. */
|
||||||
|
xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
|
||||||
|
|
||||||
|
/* We must remove ourselves from the ready list before adding
|
||||||
|
* ourselves to the blocked list as the same list item is used for
|
||||||
|
* both lists. */
|
||||||
|
( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||||
|
|
||||||
|
/* The list item will be inserted in wake time order. */
|
||||||
|
listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
|
||||||
|
|
||||||
|
if( xTimeToWake < xCoRoutineTickCount )
|
||||||
|
{
|
||||||
|
/* Wake time has overflowed. Place this item in the
|
||||||
|
* overflow list. */
|
||||||
|
vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The wake time has not overflowed, so we can use the
|
||||||
|
* current block list. */
|
||||||
|
vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pxEventList )
|
||||||
|
{
|
||||||
|
/* Also add the co-routine to an event list. If this is done then the
|
||||||
|
* function must be called with interrupts disabled. */
|
||||||
|
vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
traceRETURN_vCoRoutineAddToDelayedList();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvCheckPendingReadyList( void )
|
||||||
|
{
|
||||||
|
/* Are there any co-routines waiting to get moved to the ready list? These
|
||||||
|
* are co-routines that have been readied by an ISR. The ISR cannot access
|
||||||
|
* the ready lists itself. */
|
||||||
|
while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
|
||||||
|
{
|
||||||
|
CRCB_t * pxUnblockedCRCB;
|
||||||
|
|
||||||
|
/* The pending ready list can be accessed by an ISR. */
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
{
|
||||||
|
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyCoRoutineList ) );
|
||||||
|
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||||
|
}
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
|
||||||
|
prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvCheckDelayedList( void )
|
||||||
|
{
|
||||||
|
CRCB_t * pxCRCB;
|
||||||
|
|
||||||
|
xPassedTicks = xTaskGetTickCount() - xLastTickCount;
|
||||||
|
|
||||||
|
while( xPassedTicks )
|
||||||
|
{
|
||||||
|
xCoRoutineTickCount++;
|
||||||
|
xPassedTicks--;
|
||||||
|
|
||||||
|
/* If the tick count has overflowed we need to swap the ready lists. */
|
||||||
|
if( xCoRoutineTickCount == 0 )
|
||||||
|
{
|
||||||
|
List_t * pxTemp;
|
||||||
|
|
||||||
|
/* Tick count has overflowed so we need to swap the delay lists. If there are
|
||||||
|
* any items in pxDelayedCoRoutineList here then there is an error! */
|
||||||
|
pxTemp = pxDelayedCoRoutineList;
|
||||||
|
pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
|
||||||
|
pxOverflowDelayedCoRoutineList = pxTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if this tick has made a timeout expire. */
|
||||||
|
while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
|
||||||
|
{
|
||||||
|
pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
|
||||||
|
|
||||||
|
if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
|
||||||
|
{
|
||||||
|
/* Timeout not yet expired. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
{
|
||||||
|
/* The event could have occurred just before this critical
|
||||||
|
* section. If this is the case then the generic list item will
|
||||||
|
* have been moved to the pending ready list and the following
|
||||||
|
* line is still valid. Also the pvContainer parameter will have
|
||||||
|
* been set to NULL so the following lines are also valid. */
|
||||||
|
( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
|
||||||
|
|
||||||
|
/* Is the co-routine waiting on an event also? */
|
||||||
|
if( pxCRCB->xEventListItem.pxContainer )
|
||||||
|
{
|
||||||
|
( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
prvAddCoRoutineToReadyQueue( pxCRCB );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xLastTickCount = xCoRoutineTickCount;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vCoRoutineSchedule( void )
|
||||||
|
{
|
||||||
|
traceENTER_vCoRoutineSchedule();
|
||||||
|
|
||||||
|
/* Only run a co-routine after prvInitialiseCoRoutineLists() has been
|
||||||
|
* called. prvInitialiseCoRoutineLists() is called automatically when a
|
||||||
|
* co-routine is created. */
|
||||||
|
if( pxDelayedCoRoutineList != NULL )
|
||||||
|
{
|
||||||
|
/* See if any co-routines readied by events need moving to the ready lists. */
|
||||||
|
prvCheckPendingReadyList();
|
||||||
|
|
||||||
|
/* See if any delayed co-routines have timed out. */
|
||||||
|
prvCheckDelayedList();
|
||||||
|
|
||||||
|
/* Find the highest priority queue that contains ready co-routines. */
|
||||||
|
while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
|
||||||
|
{
|
||||||
|
if( uxTopCoRoutineReadyPriority == 0 )
|
||||||
|
{
|
||||||
|
/* No more co-routines to check. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
--uxTopCoRoutineReadyPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
|
||||||
|
* of the same priority get an equal share of the processor time. */
|
||||||
|
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
|
||||||
|
|
||||||
|
/* Call the co-routine. */
|
||||||
|
( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
|
||||||
|
}
|
||||||
|
|
||||||
|
traceRETURN_vCoRoutineSchedule();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvInitialiseCoRoutineLists( void )
|
||||||
|
{
|
||||||
|
UBaseType_t uxPriority;
|
||||||
|
|
||||||
|
for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
|
||||||
|
{
|
||||||
|
vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
|
||||||
|
vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
|
||||||
|
vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
|
||||||
|
|
||||||
|
/* Start with pxDelayedCoRoutineList using list1 and the
|
||||||
|
* pxOverflowDelayedCoRoutineList using list2. */
|
||||||
|
pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
|
||||||
|
pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList )
|
||||||
|
{
|
||||||
|
CRCB_t * pxUnblockedCRCB;
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
traceENTER_xCoRoutineRemoveFromEventList( pxEventList );
|
||||||
|
|
||||||
|
/* This function is called from within an interrupt. It can only access
|
||||||
|
* event lists and the pending ready list. This function assumes that a
|
||||||
|
* check has already been made to ensure pxEventList is not empty. */
|
||||||
|
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
|
||||||
|
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||||
|
vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
|
||||||
|
|
||||||
|
if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
traceRETURN_xCoRoutineRemoveFromEventList( xReturn );
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset state in this file. This state is normally initialized at start up.
|
||||||
|
* This function must be called by the application before restarting the
|
||||||
|
* scheduler.
|
||||||
|
*/
|
||||||
|
void vCoRoutineResetState( void )
|
||||||
|
{
|
||||||
|
/* Lists for ready and blocked co-routines. */
|
||||||
|
pxDelayedCoRoutineList = NULL;
|
||||||
|
pxOverflowDelayedCoRoutineList = NULL;
|
||||||
|
|
||||||
|
/* Other file private variables. */
|
||||||
|
pxCurrentCoRoutine = NULL;
|
||||||
|
uxTopCoRoutineReadyPriority = ( UBaseType_t ) 0U;
|
||||||
|
xCoRoutineTickCount = ( TickType_t ) 0U;
|
||||||
|
xLastTickCount = ( TickType_t ) 0U;
|
||||||
|
xPassedTicks = ( TickType_t ) 0U;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#endif /* configUSE_CO_ROUTINES == 0 */
|
||||||
@@ -0,0 +1,887 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||||
|
* all the API functions to use the MPU wrappers. That should only be done when
|
||||||
|
* task.h is included from an application file. */
|
||||||
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/* FreeRTOS includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "timers.h"
|
||||||
|
#include "event_groups.h"
|
||||||
|
|
||||||
|
/* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
|
||||||
|
* for the header files above, but not in this file, in order to generate the
|
||||||
|
* correct privileged Vs unprivileged linkage and placement. */
|
||||||
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/* This entire source file will be skipped if the application is not configured
|
||||||
|
* to include event groups functionality. This #if is closed at the very bottom
|
||||||
|
* of this file. If you want to include event groups then ensure
|
||||||
|
* configUSE_EVENT_GROUPS is set to 1 in FreeRTOSConfig.h. */
|
||||||
|
#if ( configUSE_EVENT_GROUPS == 1 )
|
||||||
|
|
||||||
|
typedef struct EventGroupDef_t
|
||||||
|
{
|
||||||
|
EventBits_t uxEventBits;
|
||||||
|
List_t xTasksWaitingForBits; /**< List of tasks waiting for a bit to be set. */
|
||||||
|
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
UBaseType_t uxEventGroupNumber;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||||
|
uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
|
||||||
|
#endif
|
||||||
|
} EventGroup_t;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test the bits set in uxCurrentEventBits to see if the wait condition is met.
|
||||||
|
* The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
|
||||||
|
* pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
|
||||||
|
* are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
|
||||||
|
* wait condition is met if any of the bits set in uxBitsToWaitFor are also set
|
||||||
|
* in uxCurrentEventBits.
|
||||||
|
*/
|
||||||
|
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
|
||||||
|
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
|
||||||
|
{
|
||||||
|
EventGroup_t * pxEventBits;
|
||||||
|
|
||||||
|
traceENTER_xEventGroupCreateStatic( pxEventGroupBuffer );
|
||||||
|
|
||||||
|
/* A StaticEventGroup_t object must be provided. */
|
||||||
|
configASSERT( pxEventGroupBuffer );
|
||||||
|
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
/* Sanity check that the size of the structure used to declare a
|
||||||
|
* variable of type StaticEventGroup_t equals the size of the real
|
||||||
|
* event group structure. */
|
||||||
|
volatile size_t xSize = sizeof( StaticEventGroup_t );
|
||||||
|
configASSERT( xSize == sizeof( EventGroup_t ) );
|
||||||
|
}
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/* The user has provided a statically allocated event group - use it. */
|
||||||
|
/* MISRA Ref 11.3.1 [Misaligned access] */
|
||||||
|
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
|
||||||
|
/* coverity[misra_c_2012_rule_11_3_violation] */
|
||||||
|
pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer;
|
||||||
|
|
||||||
|
if( pxEventBits != NULL )
|
||||||
|
{
|
||||||
|
pxEventBits->uxEventBits = 0;
|
||||||
|
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
||||||
|
|
||||||
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
|
{
|
||||||
|
/* Both static and dynamic allocation can be used, so note that
|
||||||
|
* this event group was created statically in case the event group
|
||||||
|
* is later deleted. */
|
||||||
|
pxEventBits->ucStaticallyAllocated = pdTRUE;
|
||||||
|
}
|
||||||
|
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||||
|
|
||||||
|
traceEVENT_GROUP_CREATE( pxEventBits );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* xEventGroupCreateStatic should only ever be called with
|
||||||
|
* pxEventGroupBuffer pointing to a pre-allocated (compile time
|
||||||
|
* allocated) StaticEventGroup_t variable. */
|
||||||
|
traceEVENT_GROUP_CREATE_FAILED();
|
||||||
|
}
|
||||||
|
|
||||||
|
traceRETURN_xEventGroupCreateStatic( pxEventBits );
|
||||||
|
|
||||||
|
return pxEventBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
|
|
||||||
|
EventGroupHandle_t xEventGroupCreate( void )
|
||||||
|
{
|
||||||
|
EventGroup_t * pxEventBits;
|
||||||
|
|
||||||
|
traceENTER_xEventGroupCreate();
|
||||||
|
|
||||||
|
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
|
||||||
|
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||||
|
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||||
|
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
|
||||||
|
|
||||||
|
if( pxEventBits != NULL )
|
||||||
|
{
|
||||||
|
pxEventBits->uxEventBits = 0;
|
||||||
|
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
||||||
|
|
||||||
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
{
|
||||||
|
/* Both static and dynamic allocation can be used, so note this
|
||||||
|
* event group was allocated statically in case the event group is
|
||||||
|
* later deleted. */
|
||||||
|
pxEventBits->ucStaticallyAllocated = pdFALSE;
|
||||||
|
}
|
||||||
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||||
|
|
||||||
|
traceEVENT_GROUP_CREATE( pxEventBits );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
traceEVENT_GROUP_CREATE_FAILED();
|
||||||
|
}
|
||||||
|
|
||||||
|
traceRETURN_xEventGroupCreate( pxEventBits );
|
||||||
|
|
||||||
|
return pxEventBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
TickType_t xTicksToWait )
|
||||||
|
{
|
||||||
|
EventBits_t uxOriginalBitValue, uxReturn;
|
||||||
|
EventGroup_t * pxEventBits = xEventGroup;
|
||||||
|
BaseType_t xAlreadyYielded;
|
||||||
|
BaseType_t xTimeoutOccurred = pdFALSE;
|
||||||
|
|
||||||
|
traceENTER_xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait );
|
||||||
|
|
||||||
|
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||||
|
configASSERT( uxBitsToWaitFor != 0 );
|
||||||
|
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||||
|
{
|
||||||
|
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
uxOriginalBitValue = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
|
( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
|
||||||
|
|
||||||
|
if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||||
|
{
|
||||||
|
/* All the rendezvous bits are now set - no need to block. */
|
||||||
|
uxReturn = ( uxOriginalBitValue | uxBitsToSet );
|
||||||
|
|
||||||
|
/* Rendezvous always clear the bits. They will have been cleared
|
||||||
|
* already unless this is the only task in the rendezvous. */
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||||
|
|
||||||
|
xTicksToWait = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( xTicksToWait != ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
|
||||||
|
|
||||||
|
/* Store the bits that the calling task is waiting for in the
|
||||||
|
* task's event list item so the kernel knows when a match is
|
||||||
|
* found. Then enter the blocked state. */
|
||||||
|
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
|
||||||
|
|
||||||
|
/* This assignment is obsolete as uxReturn will get set after
|
||||||
|
* the task unblocks, but some compilers mistakenly generate a
|
||||||
|
* warning about uxReturn being returned without being set if the
|
||||||
|
* assignment is omitted. */
|
||||||
|
uxReturn = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The rendezvous bits were not set, but no block time was
|
||||||
|
* specified - just return the current event bit value. */
|
||||||
|
uxReturn = pxEventBits->uxEventBits;
|
||||||
|
xTimeoutOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xAlreadyYielded = xTaskResumeAll();
|
||||||
|
|
||||||
|
if( xTicksToWait != ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
if( xAlreadyYielded == pdFALSE )
|
||||||
|
{
|
||||||
|
taskYIELD_WITHIN_API();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The task blocked to wait for its required bits to be set - at this
|
||||||
|
* point either the required bits were set or the block time expired. If
|
||||||
|
* the required bits were set they will have been stored in the task's
|
||||||
|
* event list item, and they should now be retrieved then cleared. */
|
||||||
|
uxReturn = uxTaskResetEventItemValue();
|
||||||
|
|
||||||
|
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
/* The task timed out, just return the current event bit value. */
|
||||||
|
taskENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
uxReturn = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
|
/* Although the task got here because it timed out before the
|
||||||
|
* bits it was waiting for were set, it is possible that since it
|
||||||
|
* unblocked another task has set the bits. If this is the case
|
||||||
|
* then it needs to clear the bits before exiting. */
|
||||||
|
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||||
|
{
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL();
|
||||||
|
|
||||||
|
xTimeoutOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The task unblocked because the bits were set. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Control bits might be set as the task had blocked should not be
|
||||||
|
* returned. */
|
||||||
|
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
|
||||||
|
|
||||||
|
/* Prevent compiler warnings when trace macros are not used. */
|
||||||
|
( void ) xTimeoutOccurred;
|
||||||
|
|
||||||
|
traceRETURN_xEventGroupSync( uxReturn );
|
||||||
|
|
||||||
|
return uxReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
const BaseType_t xClearOnExit,
|
||||||
|
const BaseType_t xWaitForAllBits,
|
||||||
|
TickType_t xTicksToWait )
|
||||||
|
{
|
||||||
|
EventGroup_t * pxEventBits = xEventGroup;
|
||||||
|
EventBits_t uxReturn, uxControlBits = 0;
|
||||||
|
BaseType_t xWaitConditionMet, xAlreadyYielded;
|
||||||
|
BaseType_t xTimeoutOccurred = pdFALSE;
|
||||||
|
|
||||||
|
traceENTER_xEventGroupWaitBits( xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait );
|
||||||
|
|
||||||
|
/* Check the user is not attempting to wait on the bits used by the kernel
|
||||||
|
* itself, and that at least one bit is being requested. */
|
||||||
|
configASSERT( xEventGroup );
|
||||||
|
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||||
|
configASSERT( uxBitsToWaitFor != 0 );
|
||||||
|
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||||
|
{
|
||||||
|
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
|
/* Check to see if the wait condition is already met or not. */
|
||||||
|
xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
|
||||||
|
|
||||||
|
if( xWaitConditionMet != pdFALSE )
|
||||||
|
{
|
||||||
|
/* The wait condition has already been met so there is no need to
|
||||||
|
* block. */
|
||||||
|
uxReturn = uxCurrentEventBits;
|
||||||
|
xTicksToWait = ( TickType_t ) 0;
|
||||||
|
|
||||||
|
/* Clear the wait bits if requested to do so. */
|
||||||
|
if( xClearOnExit != pdFALSE )
|
||||||
|
{
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( xTicksToWait == ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
/* The wait condition has not been met, but no block time was
|
||||||
|
* specified, so just return the current value. */
|
||||||
|
uxReturn = uxCurrentEventBits;
|
||||||
|
xTimeoutOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The task is going to block to wait for its required bits to be
|
||||||
|
* set. uxControlBits are used to remember the specified behaviour of
|
||||||
|
* this call to xEventGroupWaitBits() - for use when the event bits
|
||||||
|
* unblock the task. */
|
||||||
|
if( xClearOnExit != pdFALSE )
|
||||||
|
{
|
||||||
|
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xWaitForAllBits != pdFALSE )
|
||||||
|
{
|
||||||
|
uxControlBits |= eventWAIT_FOR_ALL_BITS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the bits that the calling task is waiting for in the
|
||||||
|
* task's event list item so the kernel knows when a match is
|
||||||
|
* found. Then enter the blocked state. */
|
||||||
|
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
|
||||||
|
|
||||||
|
/* This is obsolete as it will get set after the task unblocks, but
|
||||||
|
* some compilers mistakenly generate a warning about the variable
|
||||||
|
* being returned without being set if it is not done. */
|
||||||
|
uxReturn = 0;
|
||||||
|
|
||||||
|
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xAlreadyYielded = xTaskResumeAll();
|
||||||
|
|
||||||
|
if( xTicksToWait != ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
if( xAlreadyYielded == pdFALSE )
|
||||||
|
{
|
||||||
|
taskYIELD_WITHIN_API();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The task blocked to wait for its required bits to be set - at this
|
||||||
|
* point either the required bits were set or the block time expired. If
|
||||||
|
* the required bits were set they will have been stored in the task's
|
||||||
|
* event list item, and they should now be retrieved then cleared. */
|
||||||
|
uxReturn = uxTaskResetEventItemValue();
|
||||||
|
|
||||||
|
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
taskENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
/* The task timed out, just return the current event bit value. */
|
||||||
|
uxReturn = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
|
/* It is possible that the event bits were updated between this
|
||||||
|
* task leaving the Blocked state and running again. */
|
||||||
|
if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
|
||||||
|
{
|
||||||
|
if( xClearOnExit != pdFALSE )
|
||||||
|
{
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
xTimeoutOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The task unblocked because the bits were set. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The task blocked so control bits may have been set. */
|
||||||
|
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
|
||||||
|
|
||||||
|
/* Prevent compiler warnings when trace macros are not used. */
|
||||||
|
( void ) xTimeoutOccurred;
|
||||||
|
|
||||||
|
traceRETURN_xEventGroupWaitBits( uxReturn );
|
||||||
|
|
||||||
|
return uxReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear )
|
||||||
|
{
|
||||||
|
EventGroup_t * pxEventBits = xEventGroup;
|
||||||
|
EventBits_t uxReturn;
|
||||||
|
|
||||||
|
traceENTER_xEventGroupClearBits( xEventGroup, uxBitsToClear );
|
||||||
|
|
||||||
|
/* Check the user is not attempting to clear the bits used by the kernel
|
||||||
|
* itself. */
|
||||||
|
configASSERT( xEventGroup );
|
||||||
|
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||||
|
|
||||||
|
taskENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
|
||||||
|
|
||||||
|
/* The value returned is the event group value prior to the bits being
|
||||||
|
* cleared. */
|
||||||
|
uxReturn = pxEventBits->uxEventBits;
|
||||||
|
|
||||||
|
/* Clear the bits. */
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToClear;
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL();
|
||||||
|
|
||||||
|
traceRETURN_xEventGroupClearBits( uxReturn );
|
||||||
|
|
||||||
|
return uxReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||||
|
|
||||||
|
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear );
|
||||||
|
|
||||||
|
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
|
||||||
|
xReturn = xTimerPendFunctionCallFromISR( &vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
|
||||||
|
|
||||||
|
traceRETURN_xEventGroupClearBitsFromISR( xReturn );
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
|
||||||
|
{
|
||||||
|
UBaseType_t uxSavedInterruptStatus;
|
||||||
|
EventGroup_t const * const pxEventBits = xEventGroup;
|
||||||
|
EventBits_t uxReturn;
|
||||||
|
|
||||||
|
traceENTER_xEventGroupGetBitsFromISR( xEventGroup );
|
||||||
|
|
||||||
|
/* MISRA Ref 4.7.1 [Return value shall be checked] */
|
||||||
|
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */
|
||||||
|
/* coverity[misra_c_2012_directive_4_7_violation] */
|
||||||
|
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
|
||||||
|
{
|
||||||
|
uxReturn = pxEventBits->uxEventBits;
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
|
||||||
|
|
||||||
|
traceRETURN_xEventGroupGetBitsFromISR( uxReturn );
|
||||||
|
|
||||||
|
return uxReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet )
|
||||||
|
{
|
||||||
|
ListItem_t * pxListItem;
|
||||||
|
ListItem_t * pxNext;
|
||||||
|
ListItem_t const * pxListEnd;
|
||||||
|
List_t const * pxList;
|
||||||
|
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits, uxReturnBits;
|
||||||
|
EventGroup_t * pxEventBits = xEventGroup;
|
||||||
|
BaseType_t xMatchFound = pdFALSE;
|
||||||
|
|
||||||
|
traceENTER_xEventGroupSetBits( xEventGroup, uxBitsToSet );
|
||||||
|
|
||||||
|
/* Check the user is not attempting to set the bits used by the kernel
|
||||||
|
* itself. */
|
||||||
|
configASSERT( xEventGroup );
|
||||||
|
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||||
|
|
||||||
|
pxList = &( pxEventBits->xTasksWaitingForBits );
|
||||||
|
pxListEnd = listGET_END_MARKER( pxList );
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
|
||||||
|
|
||||||
|
pxListItem = listGET_HEAD_ENTRY( pxList );
|
||||||
|
|
||||||
|
/* Set the bits. */
|
||||||
|
pxEventBits->uxEventBits |= uxBitsToSet;
|
||||||
|
|
||||||
|
/* See if the new bit value should unblock any tasks. */
|
||||||
|
while( pxListItem != pxListEnd )
|
||||||
|
{
|
||||||
|
pxNext = listGET_NEXT( pxListItem );
|
||||||
|
uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
|
||||||
|
xMatchFound = pdFALSE;
|
||||||
|
|
||||||
|
/* Split the bits waited for from the control bits. */
|
||||||
|
uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
|
||||||
|
uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||||
|
|
||||||
|
if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
/* Just looking for single bit being set. */
|
||||||
|
if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
xMatchFound = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
|
||||||
|
{
|
||||||
|
/* All bits are set. */
|
||||||
|
xMatchFound = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Need all bits to be set, but not all the bits were set. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xMatchFound != pdFALSE )
|
||||||
|
{
|
||||||
|
/* The bits match. Should the bits be cleared on exit? */
|
||||||
|
if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
uxBitsToClear |= uxBitsWaitedFor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the actual event flag value in the task's event list
|
||||||
|
* item before removing the task from the event list. The
|
||||||
|
* eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
|
||||||
|
* that is was unblocked due to its required bits matching, rather
|
||||||
|
* than because it timed out. */
|
||||||
|
vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move onto the next list item. Note pxListItem->pxNext is not
|
||||||
|
* used here as the list item may have been removed from the event list
|
||||||
|
* and inserted into the ready/pending reading list. */
|
||||||
|
pxListItem = pxNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
|
||||||
|
* bit was set in the control word. */
|
||||||
|
pxEventBits->uxEventBits &= ~uxBitsToClear;
|
||||||
|
|
||||||
|
/* Snapshot resulting bits. */
|
||||||
|
uxReturnBits = pxEventBits->uxEventBits;
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
|
||||||
|
traceRETURN_xEventGroupSetBits( uxReturnBits );
|
||||||
|
|
||||||
|
return uxReturnBits;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
|
||||||
|
{
|
||||||
|
EventGroup_t * pxEventBits = xEventGroup;
|
||||||
|
const List_t * pxTasksWaitingForBits;
|
||||||
|
|
||||||
|
traceENTER_vEventGroupDelete( xEventGroup );
|
||||||
|
|
||||||
|
configASSERT( pxEventBits );
|
||||||
|
|
||||||
|
pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
traceEVENT_GROUP_DELETE( xEventGroup );
|
||||||
|
|
||||||
|
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
|
||||||
|
{
|
||||||
|
/* Unblock the task, returning 0 as the event list is being deleted
|
||||||
|
* and cannot therefore have any bits set. */
|
||||||
|
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
|
||||||
|
vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
|
||||||
|
#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
|
||||||
|
{
|
||||||
|
/* The event group can only have been allocated dynamically - free
|
||||||
|
* it again. */
|
||||||
|
vPortFree( pxEventBits );
|
||||||
|
}
|
||||||
|
#elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
|
||||||
|
{
|
||||||
|
/* The event group could have been allocated statically or
|
||||||
|
* dynamically, so check before attempting to free the memory. */
|
||||||
|
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
|
||||||
|
{
|
||||||
|
vPortFree( pxEventBits );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||||
|
|
||||||
|
traceRETURN_vEventGroupDelete();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
|
||||||
|
StaticEventGroup_t ** ppxEventGroupBuffer )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
EventGroup_t * pxEventBits = xEventGroup;
|
||||||
|
|
||||||
|
traceENTER_xEventGroupGetStaticBuffer( xEventGroup, ppxEventGroupBuffer );
|
||||||
|
|
||||||
|
configASSERT( pxEventBits );
|
||||||
|
configASSERT( ppxEventGroupBuffer );
|
||||||
|
|
||||||
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
|
{
|
||||||
|
/* Check if the event group was statically allocated. */
|
||||||
|
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdTRUE )
|
||||||
|
{
|
||||||
|
/* MISRA Ref 11.3.1 [Misaligned access] */
|
||||||
|
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
|
||||||
|
/* coverity[misra_c_2012_rule_11_3_violation] */
|
||||||
|
*ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||||
|
{
|
||||||
|
/* Event group must have been statically allocated. */
|
||||||
|
/* MISRA Ref 11.3.1 [Misaligned access] */
|
||||||
|
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
|
||||||
|
/* coverity[misra_c_2012_rule_11_3_violation] */
|
||||||
|
*ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits;
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||||
|
|
||||||
|
traceRETURN_xEventGroupGetStaticBuffer( xReturn );
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* For internal use only - execute a 'set bits' command that was pended from
|
||||||
|
* an interrupt. */
|
||||||
|
void vEventGroupSetBitsCallback( void * pvEventGroup,
|
||||||
|
uint32_t ulBitsToSet )
|
||||||
|
{
|
||||||
|
traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet );
|
||||||
|
|
||||||
|
/* MISRA Ref 11.5.4 [Callback function parameter] */
|
||||||
|
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||||
|
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||||
|
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );
|
||||||
|
|
||||||
|
traceRETURN_vEventGroupSetBitsCallback();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* For internal use only - execute a 'clear bits' command that was pended from
|
||||||
|
* an interrupt. */
|
||||||
|
void vEventGroupClearBitsCallback( void * pvEventGroup,
|
||||||
|
uint32_t ulBitsToClear )
|
||||||
|
{
|
||||||
|
traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear );
|
||||||
|
|
||||||
|
/* MISRA Ref 11.5.4 [Callback function parameter] */
|
||||||
|
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||||
|
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||||
|
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );
|
||||||
|
|
||||||
|
traceRETURN_vEventGroupClearBitsCallback();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
const BaseType_t xWaitForAllBits )
|
||||||
|
{
|
||||||
|
BaseType_t xWaitConditionMet = pdFALSE;
|
||||||
|
|
||||||
|
if( xWaitForAllBits == pdFALSE )
|
||||||
|
{
|
||||||
|
/* Task only has to wait for one bit within uxBitsToWaitFor to be
|
||||||
|
* set. Is one already set? */
|
||||||
|
if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
|
||||||
|
{
|
||||||
|
xWaitConditionMet = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Task has to wait for all the bits in uxBitsToWaitFor to be set.
|
||||||
|
* Are they set already? */
|
||||||
|
if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||||
|
{
|
||||||
|
xWaitConditionMet = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return xWaitConditionMet;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||||
|
|
||||||
|
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet,
|
||||||
|
BaseType_t * pxHigherPriorityTaskWoken )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken );
|
||||||
|
|
||||||
|
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
|
||||||
|
xReturn = xTimerPendFunctionCallFromISR( &vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
|
||||||
|
|
||||||
|
traceRETURN_xEventGroupSetBitsFromISR( xReturn );
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
|
||||||
|
UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
|
||||||
|
{
|
||||||
|
UBaseType_t xReturn;
|
||||||
|
|
||||||
|
/* MISRA Ref 11.5.2 [Opaque pointer] */
|
||||||
|
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||||
|
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||||
|
EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||||
|
|
||||||
|
traceENTER_uxEventGroupGetNumber( xEventGroup );
|
||||||
|
|
||||||
|
if( xEventGroup == NULL )
|
||||||
|
{
|
||||||
|
xReturn = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pxEventBits->uxEventGroupNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
traceRETURN_uxEventGroupGetNumber( xReturn );
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configUSE_TRACE_FACILITY */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
|
||||||
|
void vEventGroupSetNumber( void * xEventGroup,
|
||||||
|
UBaseType_t uxEventGroupNumber )
|
||||||
|
{
|
||||||
|
traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber );
|
||||||
|
|
||||||
|
/* MISRA Ref 11.5.2 [Opaque pointer] */
|
||||||
|
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
|
||||||
|
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||||
|
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber;
|
||||||
|
|
||||||
|
traceRETURN_vEventGroupSetNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configUSE_TRACE_FACILITY */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This entire source file will be skipped if the application is not configured
|
||||||
|
* to include event groups functionality. If you want to include event groups
|
||||||
|
* then ensure configUSE_EVENT_GROUPS is set to 1 in FreeRTOSConfig.h. */
|
||||||
|
#endif /* configUSE_EVENT_GROUPS == 1 */
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# FreeRTOS internal cmake file. Do not use it in user top-level project
|
||||||
|
|
||||||
|
add_library(freertos_kernel_include INTERFACE)
|
||||||
|
|
||||||
|
target_include_directories(freertos_kernel_include
|
||||||
|
INTERFACE
|
||||||
|
.
|
||||||
|
# Note: DEPRECATED but still supported, may be removed in a future release.
|
||||||
|
$<$<NOT:$<TARGET_EXISTS:freertos_config>>:${FREERTOS_CONFIG_FILE_DIRECTORY}>
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(freertos_kernel_include
|
||||||
|
INTERFACE
|
||||||
|
$<$<TARGET_EXISTS:freertos_config>:freertos_config>
|
||||||
|
)
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _MSC_VER /* Visual Studio doesn't support #warning. */
|
||||||
|
#warning The name of this file has changed to stack_macros.h. Please update your code accordingly. This source file (which has the original name) will be removed in a future release.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "stack_macros.h"
|
||||||
@@ -0,0 +1,427 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file atomic.h
|
||||||
|
* @brief FreeRTOS atomic operation support.
|
||||||
|
*
|
||||||
|
* This file implements atomic functions by disabling interrupts globally.
|
||||||
|
* Implementations with architecture specific atomic instructions can be
|
||||||
|
* provided under each compiler directory.
|
||||||
|
*
|
||||||
|
* The atomic interface can be used in FreeRTOS tasks on all FreeRTOS ports. It
|
||||||
|
* can also be used in Interrupt Service Routines (ISRs) on FreeRTOS ports that
|
||||||
|
* support nested interrupts (i.e. portHAS_NESTED_INTERRUPTS is set to 1). The
|
||||||
|
* atomic interface must not be used in ISRs on FreeRTOS ports that do not
|
||||||
|
* support nested interrupts (i.e. portHAS_NESTED_INTERRUPTS is set to 0)
|
||||||
|
* because ISRs on these ports cannot be interrupted and therefore, do not need
|
||||||
|
* atomics in ISRs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ATOMIC_H
|
||||||
|
#define ATOMIC_H
|
||||||
|
|
||||||
|
#ifndef INC_FREERTOS_H
|
||||||
|
#error "include FreeRTOS.h must appear in source files before include atomic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port specific definitions -- entering/exiting critical section.
|
||||||
|
* Refer template -- ./lib/FreeRTOS/portable/Compiler/Arch/portmacro.h
|
||||||
|
*
|
||||||
|
* Every call to ATOMIC_EXIT_CRITICAL() must be closely paired with
|
||||||
|
* ATOMIC_ENTER_CRITICAL().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if ( portHAS_NESTED_INTERRUPTS == 1 )
|
||||||
|
|
||||||
|
/* Nested interrupt scheme is supported in this port. */
|
||||||
|
#define ATOMIC_ENTER_CRITICAL() \
|
||||||
|
UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR()
|
||||||
|
|
||||||
|
#define ATOMIC_EXIT_CRITICAL() \
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType )
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* Nested interrupt scheme is NOT supported in this port. */
|
||||||
|
#define ATOMIC_ENTER_CRITICAL() portENTER_CRITICAL()
|
||||||
|
#define ATOMIC_EXIT_CRITICAL() portEXIT_CRITICAL()
|
||||||
|
|
||||||
|
#endif /* portSET_INTERRUPT_MASK_FROM_ISR() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port specific definition -- "always inline".
|
||||||
|
* Inline is compiler specific, and may not always get inlined depending on your
|
||||||
|
* optimization level. Also, inline is considered as performance optimization
|
||||||
|
* for atomic. Thus, if portFORCE_INLINE is not provided by portmacro.h,
|
||||||
|
* instead of resulting error, simply define it away.
|
||||||
|
*/
|
||||||
|
#ifndef portFORCE_INLINE
|
||||||
|
#define portFORCE_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ATOMIC_COMPARE_AND_SWAP_SUCCESS 0x1U /**< Compare and swap succeeded, swapped. */
|
||||||
|
#define ATOMIC_COMPARE_AND_SWAP_FAILURE 0x0U /**< Compare and swap failed, did not swap. */
|
||||||
|
|
||||||
|
/*----------------------------- Swap && CAS ------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic compare-and-swap
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic compare-and-swap operation on the specified values.
|
||||||
|
*
|
||||||
|
* @param[in, out] pulDestination Pointer to memory location from where value is
|
||||||
|
* to be loaded and checked.
|
||||||
|
* @param[in] ulExchange If condition meets, write this value to memory.
|
||||||
|
* @param[in] ulComparand Swap condition.
|
||||||
|
*
|
||||||
|
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
|
||||||
|
*
|
||||||
|
* @note This function only swaps *pulDestination with ulExchange, if previous
|
||||||
|
* *pulDestination value equals ulComparand.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( uint32_t volatile * pulDestination,
|
||||||
|
uint32_t ulExchange,
|
||||||
|
uint32_t ulComparand )
|
||||||
|
{
|
||||||
|
uint32_t ulReturnValue;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
if( *pulDestination == ulComparand )
|
||||||
|
{
|
||||||
|
*pulDestination = ulExchange;
|
||||||
|
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulReturnValue;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic swap (pointers)
|
||||||
|
*
|
||||||
|
* @brief Atomically sets the address pointed to by *ppvDestination to the value
|
||||||
|
* of *pvExchange.
|
||||||
|
*
|
||||||
|
* @param[in, out] ppvDestination Pointer to memory location from where a pointer
|
||||||
|
* value is to be loaded and written back to.
|
||||||
|
* @param[in] pvExchange Pointer value to be written to *ppvDestination.
|
||||||
|
*
|
||||||
|
* @return The initial value of *ppvDestination.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE void * Atomic_SwapPointers_p32( void * volatile * ppvDestination,
|
||||||
|
void * pvExchange )
|
||||||
|
{
|
||||||
|
void * pReturnValue;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
pReturnValue = *ppvDestination;
|
||||||
|
*ppvDestination = pvExchange;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return pReturnValue;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic compare-and-swap (pointers)
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic compare-and-swap operation on the specified pointer
|
||||||
|
* values.
|
||||||
|
*
|
||||||
|
* @param[in, out] ppvDestination Pointer to memory location from where a pointer
|
||||||
|
* value is to be loaded and checked.
|
||||||
|
* @param[in] pvExchange If condition meets, write this value to memory.
|
||||||
|
* @param[in] pvComparand Swap condition.
|
||||||
|
*
|
||||||
|
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
|
||||||
|
*
|
||||||
|
* @note This function only swaps *ppvDestination with pvExchange, if previous
|
||||||
|
* *ppvDestination value equals pvComparand.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( void * volatile * ppvDestination,
|
||||||
|
void * pvExchange,
|
||||||
|
void * pvComparand )
|
||||||
|
{
|
||||||
|
uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
if( *ppvDestination == pvComparand )
|
||||||
|
{
|
||||||
|
*ppvDestination = pvExchange;
|
||||||
|
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulReturnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------- Arithmetic ------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic add
|
||||||
|
*
|
||||||
|
* @brief Atomically adds count to the value of the specified pointer points to.
|
||||||
|
*
|
||||||
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
|
* loaded and written back to.
|
||||||
|
* @param[in] ulCount Value to be added to *pulAddend.
|
||||||
|
*
|
||||||
|
* @return previous *pulAddend value.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend,
|
||||||
|
uint32_t ulCount )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend += ulCount;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic subtract
|
||||||
|
*
|
||||||
|
* @brief Atomically subtracts count from the value of the specified pointer
|
||||||
|
* pointers to.
|
||||||
|
*
|
||||||
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
|
* loaded and written back to.
|
||||||
|
* @param[in] ulCount Value to be subtract from *pulAddend.
|
||||||
|
*
|
||||||
|
* @return previous *pulAddend value.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAddend,
|
||||||
|
uint32_t ulCount )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend -= ulCount;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic increment
|
||||||
|
*
|
||||||
|
* @brief Atomically increments the value of the specified pointer points to.
|
||||||
|
*
|
||||||
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
|
* loaded and written back to.
|
||||||
|
*
|
||||||
|
* @return *pulAddend value before increment.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pulAddend )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend += 1;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic decrement
|
||||||
|
*
|
||||||
|
* @brief Atomically decrements the value of the specified pointer points to
|
||||||
|
*
|
||||||
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
|
* loaded and written back to.
|
||||||
|
*
|
||||||
|
* @return *pulAddend value before decrement.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pulAddend )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend -= 1;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------- Bitwise Logical ------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic OR
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic OR operation on the specified values.
|
||||||
|
*
|
||||||
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
|
* to be loaded and written back to.
|
||||||
|
* @param [in] ulValue Value to be ORed with *pulDestination.
|
||||||
|
*
|
||||||
|
* @return The original value of *pulDestination.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_OR_u32( uint32_t volatile * pulDestination,
|
||||||
|
uint32_t ulValue )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination |= ulValue;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic AND
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic AND operation on the specified values.
|
||||||
|
*
|
||||||
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
|
* to be loaded and written back to.
|
||||||
|
* @param [in] ulValue Value to be ANDed with *pulDestination.
|
||||||
|
*
|
||||||
|
* @return The original value of *pulDestination.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_AND_u32( uint32_t volatile * pulDestination,
|
||||||
|
uint32_t ulValue )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination &= ulValue;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic NAND
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic NAND operation on the specified values.
|
||||||
|
*
|
||||||
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
|
* to be loaded and written back to.
|
||||||
|
* @param [in] ulValue Value to be NANDed with *pulDestination.
|
||||||
|
*
|
||||||
|
* @return The original value of *pulDestination.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_NAND_u32( uint32_t volatile * pulDestination,
|
||||||
|
uint32_t ulValue )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination = ~( ulCurrent & ulValue );
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomic XOR
|
||||||
|
*
|
||||||
|
* @brief Performs an atomic XOR operation on the specified values.
|
||||||
|
*
|
||||||
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
|
* to be loaded and written back to.
|
||||||
|
* @param [in] ulValue Value to be XORed with *pulDestination.
|
||||||
|
*
|
||||||
|
* @return The original value of *pulDestination.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t Atomic_XOR_u32( uint32_t volatile * pulDestination,
|
||||||
|
uint32_t ulValue )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination ^= ulValue;
|
||||||
|
}
|
||||||
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
|
return ulCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* ATOMIC_H */
|
||||||
@@ -0,0 +1,765 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CO_ROUTINE_H
|
||||||
|
#define CO_ROUTINE_H
|
||||||
|
|
||||||
|
#ifndef INC_FREERTOS_H
|
||||||
|
#error "include FreeRTOS.h must appear in source files before include croutine.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/* Used to hide the implementation of the co-routine control block. The
|
||||||
|
* control block structure however has to be included in the header due to
|
||||||
|
* the macro implementation of the co-routine functionality. */
|
||||||
|
typedef void * CoRoutineHandle_t;
|
||||||
|
|
||||||
|
/* Defines the prototype to which co-routine functions must conform. */
|
||||||
|
typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t xHandle,
|
||||||
|
UBaseType_t uxIndex );
|
||||||
|
|
||||||
|
typedef struct corCoRoutineControlBlock
|
||||||
|
{
|
||||||
|
crCOROUTINE_CODE pxCoRoutineFunction;
|
||||||
|
ListItem_t xGenericListItem; /**< List item used to place the CRCB in ready and blocked queues. */
|
||||||
|
ListItem_t xEventListItem; /**< List item used to place the CRCB in event lists. */
|
||||||
|
UBaseType_t uxPriority; /**< The priority of the co-routine in relation to other co-routines. */
|
||||||
|
UBaseType_t uxIndex; /**< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
|
||||||
|
uint16_t uxState; /**< Used internally by the co-routine implementation. */
|
||||||
|
} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* @code{c}
|
||||||
|
* BaseType_t xCoRoutineCreate(
|
||||||
|
* crCOROUTINE_CODE pxCoRoutineCode,
|
||||||
|
* UBaseType_t uxPriority,
|
||||||
|
* UBaseType_t uxIndex
|
||||||
|
* );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Create a new co-routine and add it to the list of co-routines that are
|
||||||
|
* ready to run.
|
||||||
|
*
|
||||||
|
* @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
|
||||||
|
* functions require special syntax - see the co-routine section of the WEB
|
||||||
|
* documentation for more information.
|
||||||
|
*
|
||||||
|
* @param uxPriority The priority with respect to other co-routines at which
|
||||||
|
* the co-routine will run.
|
||||||
|
*
|
||||||
|
* @param uxIndex Used to distinguish between different co-routines that
|
||||||
|
* execute the same function. See the example below and the co-routine section
|
||||||
|
* of the WEB documentation for further information.
|
||||||
|
*
|
||||||
|
* @return pdPASS if the co-routine was successfully created and added to a ready
|
||||||
|
* list, otherwise an error code defined with ProjDefs.h.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // Co-routine to be created.
|
||||||
|
* void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* // This may not be necessary for const variables.
|
||||||
|
* static const char cLedToFlash[ 2 ] = { 5, 6 };
|
||||||
|
* static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
|
||||||
|
*
|
||||||
|
* // Must start every co-routine with a call to crSTART();
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // This co-routine just delays for a fixed period, then toggles
|
||||||
|
* // an LED. Two co-routines are created using this function, so
|
||||||
|
* // the uxIndex parameter is used to tell the co-routine which
|
||||||
|
* // LED to flash and how int32_t to delay. This assumes xQueue has
|
||||||
|
* // already been created.
|
||||||
|
* vParTestToggleLED( cLedToFlash[ uxIndex ] );
|
||||||
|
* crDELAY( xHandle, uxFlashRates[ uxIndex ] );
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Must end every co-routine with a call to crEND();
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Function that creates two co-routines.
|
||||||
|
* void vOtherFunction( void )
|
||||||
|
* {
|
||||||
|
* uint8_t ucParameterToPass;
|
||||||
|
* TaskHandle_t xHandle;
|
||||||
|
*
|
||||||
|
* // Create two co-routines at priority 0. The first is given index 0
|
||||||
|
* // so (from the code above) toggles LED 5 every 200 ticks. The second
|
||||||
|
* // is given index 1 so toggles LED 6 every 400 ticks.
|
||||||
|
* for( uxIndex = 0; uxIndex < 2; uxIndex++ )
|
||||||
|
* {
|
||||||
|
* xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xCoRoutineCreate xCoRoutineCreate
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
UBaseType_t uxIndex );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* @code{c}
|
||||||
|
* void vCoRoutineSchedule( void );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Run a co-routine.
|
||||||
|
*
|
||||||
|
* vCoRoutineSchedule() executes the highest priority co-routine that is able
|
||||||
|
* to run. The co-routine will execute until it either blocks, yields or is
|
||||||
|
* preempted by a task. Co-routines execute cooperatively so one
|
||||||
|
* co-routine cannot be preempted by another, but can be preempted by a task.
|
||||||
|
*
|
||||||
|
* If an application comprises of both tasks and co-routines then
|
||||||
|
* vCoRoutineSchedule should be called from the idle task (in an idle task
|
||||||
|
* hook).
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // This idle task hook will schedule a co-routine each time it is called.
|
||||||
|
* // The rest of the idle task will execute between co-routine calls.
|
||||||
|
* void vApplicationIdleHook( void )
|
||||||
|
* {
|
||||||
|
* vCoRoutineSchedule();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Alternatively, if you do not require any other part of the idle task to
|
||||||
|
* // execute, the idle task hook can call vCoRoutineSchedule() within an
|
||||||
|
* // infinite loop.
|
||||||
|
* void vApplicationIdleHook( void )
|
||||||
|
* {
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* vCoRoutineSchedule();
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup vCoRoutineSchedule vCoRoutineSchedule
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
void vCoRoutineSchedule( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* @code{c}
|
||||||
|
* crSTART( CoRoutineHandle_t xHandle );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* This macro MUST always be called at the start of a co-routine function.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // Co-routine to be created.
|
||||||
|
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* static int32_t ulAVariable;
|
||||||
|
*
|
||||||
|
* // Must start every co-routine with a call to crSTART();
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Co-routine functionality goes here.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Must end every co-routine with a call to crEND();
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup crSTART crSTART
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crSTART( pxCRCB ) \
|
||||||
|
switch( ( ( CRCB_t * ) ( pxCRCB ) )->uxState ) { \
|
||||||
|
case 0:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* @code{c}
|
||||||
|
* crEND();
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* This macro MUST always be called at the end of a co-routine function.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // Co-routine to be created.
|
||||||
|
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* static int32_t ulAVariable;
|
||||||
|
*
|
||||||
|
* // Must start every co-routine with a call to crSTART();
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Co-routine functionality goes here.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Must end every co-routine with a call to crEND();
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup crSTART crSTART
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#define crEND() }
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These macros are intended for internal use by the co-routine implementation
|
||||||
|
* only. The macros should not be used directly by application writers.
|
||||||
|
*/
|
||||||
|
#define crSET_STATE0( xHandle ) \
|
||||||
|
( ( CRCB_t * ) ( xHandle ) )->uxState = ( __LINE__ * 2 ); return; \
|
||||||
|
case ( __LINE__ * 2 ):
|
||||||
|
#define crSET_STATE1( xHandle ) \
|
||||||
|
( ( CRCB_t * ) ( xHandle ) )->uxState = ( ( __LINE__ * 2 ) + 1 ); return; \
|
||||||
|
case ( ( __LINE__ * 2 ) + 1 ):
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* @code{c}
|
||||||
|
* crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Delay a co-routine for a fixed period of time.
|
||||||
|
*
|
||||||
|
* crDELAY can only be called from the co-routine function itself - not
|
||||||
|
* from within a function called by the co-routine function. This is because
|
||||||
|
* co-routines do not maintain their own stack.
|
||||||
|
*
|
||||||
|
* @param xHandle The handle of the co-routine to delay. This is the xHandle
|
||||||
|
* parameter of the co-routine function.
|
||||||
|
*
|
||||||
|
* @param xTickToDelay The number of ticks that the co-routine should delay
|
||||||
|
* for. The actual amount of time this equates to is defined by
|
||||||
|
* configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS
|
||||||
|
* can be used to convert ticks to milliseconds.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // Co-routine to be created.
|
||||||
|
* void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* // This may not be necessary for const variables.
|
||||||
|
* // We are to delay for 200ms.
|
||||||
|
* static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
|
||||||
|
*
|
||||||
|
* // Must start every co-routine with a call to crSTART();
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Delay for 200ms.
|
||||||
|
* crDELAY( xHandle, xDelayTime );
|
||||||
|
*
|
||||||
|
* // Do something here.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Must end every co-routine with a call to crEND();
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup crDELAY crDELAY
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crDELAY( xHandle, xTicksToDelay ) \
|
||||||
|
do { \
|
||||||
|
if( ( xTicksToDelay ) > 0 ) \
|
||||||
|
{ \
|
||||||
|
vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \
|
||||||
|
} \
|
||||||
|
crSET_STATE0( ( xHandle ) ); \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @code{c}
|
||||||
|
* crQUEUE_SEND(
|
||||||
|
* CoRoutineHandle_t xHandle,
|
||||||
|
* QueueHandle_t pxQueue,
|
||||||
|
* void *pvItemToQueue,
|
||||||
|
* TickType_t xTicksToWait,
|
||||||
|
* BaseType_t *pxResult
|
||||||
|
* )
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
|
||||||
|
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
|
||||||
|
* xQueueSend() and xQueueReceive() can only be used from tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND can only be called from the co-routine function itself - not
|
||||||
|
* from within a function called by the co-routine function. This is because
|
||||||
|
* co-routines do not maintain their own stack.
|
||||||
|
*
|
||||||
|
* See the co-routine section of the WEB documentation for information on
|
||||||
|
* passing data between tasks and co-routines and between ISR's and
|
||||||
|
* co-routines.
|
||||||
|
*
|
||||||
|
* @param xHandle The handle of the calling co-routine. This is the xHandle
|
||||||
|
* parameter of the co-routine function.
|
||||||
|
*
|
||||||
|
* @param pxQueue The handle of the queue on which the data will be posted.
|
||||||
|
* The handle is obtained as the return value when the queue is created using
|
||||||
|
* the xQueueCreate() API function.
|
||||||
|
*
|
||||||
|
* @param pvItemToQueue A pointer to the data being posted onto the queue.
|
||||||
|
* The number of bytes of each queued item is specified when the queue is
|
||||||
|
* created. This number of bytes is copied from pvItemToQueue into the queue
|
||||||
|
* itself.
|
||||||
|
*
|
||||||
|
* @param xTickToDelay The number of ticks that the co-routine should block
|
||||||
|
* to wait for space to become available on the queue, should space not be
|
||||||
|
* available immediately. The actual amount of time this equates to is defined
|
||||||
|
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
|
||||||
|
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
|
||||||
|
* below).
|
||||||
|
*
|
||||||
|
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
|
||||||
|
* data was successfully posted onto the queue, otherwise it will be set to an
|
||||||
|
* error defined within ProjDefs.h.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // Co-routine function that blocks for a fixed period then posts a number onto
|
||||||
|
* // a queue.
|
||||||
|
* static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* static BaseType_t xNumberToPost = 0;
|
||||||
|
* static BaseType_t xResult;
|
||||||
|
*
|
||||||
|
* // Co-routines must begin with a call to crSTART().
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // This assumes the queue has already been created.
|
||||||
|
* crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
|
||||||
|
*
|
||||||
|
* if( xResult != pdPASS )
|
||||||
|
* {
|
||||||
|
* // The message was not posted!
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Increment the number to be posted onto the queue.
|
||||||
|
* xNumberToPost++;
|
||||||
|
*
|
||||||
|
* // Delay for 100 ticks.
|
||||||
|
* crDELAY( xHandle, 100 );
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Co-routines must end with a call to crEND().
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup crQUEUE_SEND crQUEUE_SEND
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \
|
||||||
|
do { \
|
||||||
|
*( pxResult ) = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), ( xTicksToWait ) ); \
|
||||||
|
if( *( pxResult ) == errQUEUE_BLOCKED ) \
|
||||||
|
{ \
|
||||||
|
crSET_STATE0( ( xHandle ) ); \
|
||||||
|
*pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \
|
||||||
|
} \
|
||||||
|
if( *pxResult == errQUEUE_YIELD ) \
|
||||||
|
{ \
|
||||||
|
crSET_STATE1( ( xHandle ) ); \
|
||||||
|
*pxResult = pdPASS; \
|
||||||
|
} \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* @code{c}
|
||||||
|
* crQUEUE_RECEIVE(
|
||||||
|
* CoRoutineHandle_t xHandle,
|
||||||
|
* QueueHandle_t pxQueue,
|
||||||
|
* void *pvBuffer,
|
||||||
|
* TickType_t xTicksToWait,
|
||||||
|
* BaseType_t *pxResult
|
||||||
|
* )
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
|
||||||
|
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
|
||||||
|
* xQueueSend() and xQueueReceive() can only be used from tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_RECEIVE can only be called from the co-routine function itself - not
|
||||||
|
* from within a function called by the co-routine function. This is because
|
||||||
|
* co-routines do not maintain their own stack.
|
||||||
|
*
|
||||||
|
* See the co-routine section of the WEB documentation for information on
|
||||||
|
* passing data between tasks and co-routines and between ISR's and
|
||||||
|
* co-routines.
|
||||||
|
*
|
||||||
|
* @param xHandle The handle of the calling co-routine. This is the xHandle
|
||||||
|
* parameter of the co-routine function.
|
||||||
|
*
|
||||||
|
* @param pxQueue The handle of the queue from which the data will be received.
|
||||||
|
* The handle is obtained as the return value when the queue is created using
|
||||||
|
* the xQueueCreate() API function.
|
||||||
|
*
|
||||||
|
* @param pvBuffer The buffer into which the received item is to be copied.
|
||||||
|
* The number of bytes of each queued item is specified when the queue is
|
||||||
|
* created. This number of bytes is copied into pvBuffer.
|
||||||
|
*
|
||||||
|
* @param xTickToDelay The number of ticks that the co-routine should block
|
||||||
|
* to wait for data to become available from the queue, should data not be
|
||||||
|
* available immediately. The actual amount of time this equates to is defined
|
||||||
|
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
|
||||||
|
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
|
||||||
|
* crQUEUE_SEND example).
|
||||||
|
*
|
||||||
|
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
|
||||||
|
* data was successfully retrieved from the queue, otherwise it will be set to
|
||||||
|
* an error code as defined within ProjDefs.h.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // A co-routine receives the number of an LED to flash from a queue. It
|
||||||
|
* // blocks on the queue until the number is received.
|
||||||
|
* static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||||
|
* static BaseType_t xResult;
|
||||||
|
* static UBaseType_t uxLEDToFlash;
|
||||||
|
*
|
||||||
|
* // All co-routines must start with a call to crSTART().
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Wait for data to become available on the queue.
|
||||||
|
* crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
|
||||||
|
*
|
||||||
|
* if( xResult == pdPASS )
|
||||||
|
* {
|
||||||
|
* // We received the LED to flash - flash it!
|
||||||
|
* vParTestToggleLED( uxLEDToFlash );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \
|
||||||
|
do { \
|
||||||
|
*( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), ( xTicksToWait ) ); \
|
||||||
|
if( *( pxResult ) == errQUEUE_BLOCKED ) \
|
||||||
|
{ \
|
||||||
|
crSET_STATE0( ( xHandle ) ); \
|
||||||
|
*( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), 0 ); \
|
||||||
|
} \
|
||||||
|
if( *( pxResult ) == errQUEUE_YIELD ) \
|
||||||
|
{ \
|
||||||
|
crSET_STATE1( ( xHandle ) ); \
|
||||||
|
*( pxResult ) = pdPASS; \
|
||||||
|
} \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* @code{c}
|
||||||
|
* crQUEUE_SEND_FROM_ISR(
|
||||||
|
* QueueHandle_t pxQueue,
|
||||||
|
* void *pvItemToQueue,
|
||||||
|
* BaseType_t xCoRoutinePreviouslyWoken
|
||||||
|
* )
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
|
||||||
|
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
|
||||||
|
* functions used by tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
|
||||||
|
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
|
||||||
|
* xQueueReceiveFromISR() can only be used to pass data between a task and and
|
||||||
|
* ISR.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
|
||||||
|
* that is being used from within a co-routine.
|
||||||
|
*
|
||||||
|
* See the co-routine section of the WEB documentation for information on
|
||||||
|
* passing data between tasks and co-routines and between ISR's and
|
||||||
|
* co-routines.
|
||||||
|
*
|
||||||
|
* @param xQueue The handle to the queue on which the item is to be posted.
|
||||||
|
*
|
||||||
|
* @param pvItemToQueue A pointer to the item that is to be placed on the
|
||||||
|
* queue. The size of the items the queue will hold was defined when the
|
||||||
|
* queue was created, so this many bytes will be copied from pvItemToQueue
|
||||||
|
* into the queue storage area.
|
||||||
|
*
|
||||||
|
* @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
|
||||||
|
* the same queue multiple times from a single interrupt. The first call
|
||||||
|
* should always pass in pdFALSE. Subsequent calls should pass in
|
||||||
|
* the value returned from the previous call.
|
||||||
|
*
|
||||||
|
* @return pdTRUE if a co-routine was woken by posting onto the queue. This is
|
||||||
|
* used by the ISR to determine if a context switch may be required following
|
||||||
|
* the ISR.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // A co-routine that blocks on a queue waiting for characters to be received.
|
||||||
|
* static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* char cRxedChar;
|
||||||
|
* BaseType_t xResult;
|
||||||
|
*
|
||||||
|
* // All co-routines must start with a call to crSTART().
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Wait for data to become available on the queue. This assumes the
|
||||||
|
* // queue xCommsRxQueue has already been created!
|
||||||
|
* crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
|
||||||
|
*
|
||||||
|
* // Was a character received?
|
||||||
|
* if( xResult == pdPASS )
|
||||||
|
* {
|
||||||
|
* // Process the character here.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // All co-routines must end with a call to crEND().
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // An ISR that uses a queue to send characters received on a serial port to
|
||||||
|
* // a co-routine.
|
||||||
|
* void vUART_ISR( void )
|
||||||
|
* {
|
||||||
|
* char cRxedChar;
|
||||||
|
* BaseType_t xCRWokenByPost = pdFALSE;
|
||||||
|
*
|
||||||
|
* // We loop around reading characters until there are none left in the UART.
|
||||||
|
* while( UART_RX_REG_NOT_EMPTY() )
|
||||||
|
* {
|
||||||
|
* // Obtain the character from the UART.
|
||||||
|
* cRxedChar = UART_RX_REG;
|
||||||
|
*
|
||||||
|
* // Post the character onto a queue. xCRWokenByPost will be pdFALSE
|
||||||
|
* // the first time around the loop. If the post causes a co-routine
|
||||||
|
* // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
|
||||||
|
* // In this manner we can ensure that if more than one co-routine is
|
||||||
|
* // blocked on the queue only one is woken by this ISR no matter how
|
||||||
|
* // many characters are posted to the queue.
|
||||||
|
* xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) \
|
||||||
|
xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* croutine. h
|
||||||
|
* @code{c}
|
||||||
|
* crQUEUE_SEND_FROM_ISR(
|
||||||
|
* QueueHandle_t pxQueue,
|
||||||
|
* void *pvBuffer,
|
||||||
|
* BaseType_t * pxCoRoutineWoken
|
||||||
|
* )
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
|
||||||
|
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
|
||||||
|
* functions used by tasks.
|
||||||
|
*
|
||||||
|
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
|
||||||
|
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
|
||||||
|
* xQueueReceiveFromISR() can only be used to pass data between a task and and
|
||||||
|
* ISR.
|
||||||
|
*
|
||||||
|
* crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
|
||||||
|
* from a queue that is being used from within a co-routine (a co-routine
|
||||||
|
* posted to the queue).
|
||||||
|
*
|
||||||
|
* See the co-routine section of the WEB documentation for information on
|
||||||
|
* passing data between tasks and co-routines and between ISR's and
|
||||||
|
* co-routines.
|
||||||
|
*
|
||||||
|
* @param xQueue The handle to the queue on which the item is to be posted.
|
||||||
|
*
|
||||||
|
* @param pvBuffer A pointer to a buffer into which the received item will be
|
||||||
|
* placed. The size of the items the queue will hold was defined when the
|
||||||
|
* queue was created, so this many bytes will be copied from the queue into
|
||||||
|
* pvBuffer.
|
||||||
|
*
|
||||||
|
* @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
|
||||||
|
* available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a
|
||||||
|
* co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
|
||||||
|
* *pxCoRoutineWoken will remain unchanged.
|
||||||
|
*
|
||||||
|
* @return pdTRUE an item was successfully received from the queue, otherwise
|
||||||
|
* pdFALSE.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // A co-routine that posts a character to a queue then blocks for a fixed
|
||||||
|
* // period. The character is incremented each time.
|
||||||
|
* static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
* {
|
||||||
|
* // cChar holds its value while this co-routine is blocked and must therefore
|
||||||
|
* // be declared static.
|
||||||
|
* static char cCharToTx = 'a';
|
||||||
|
* BaseType_t xResult;
|
||||||
|
*
|
||||||
|
* // All co-routines must start with a call to crSTART().
|
||||||
|
* crSTART( xHandle );
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Send the next character to the queue.
|
||||||
|
* crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
|
||||||
|
*
|
||||||
|
* if( xResult == pdPASS )
|
||||||
|
* {
|
||||||
|
* // The character was successfully posted to the queue.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // Could not post the character to the queue.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Enable the UART Tx interrupt to cause an interrupt in this
|
||||||
|
* // hypothetical UART. The interrupt will obtain the character
|
||||||
|
* // from the queue and send it.
|
||||||
|
* ENABLE_RX_INTERRUPT();
|
||||||
|
*
|
||||||
|
* // Increment to the next character then block for a fixed period.
|
||||||
|
* // cCharToTx will maintain its value across the delay as it is
|
||||||
|
* // declared static.
|
||||||
|
* cCharToTx++;
|
||||||
|
* if( cCharToTx > 'x' )
|
||||||
|
* {
|
||||||
|
* cCharToTx = 'a';
|
||||||
|
* }
|
||||||
|
* crDELAY( 100 );
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // All co-routines must end with a call to crEND().
|
||||||
|
* crEND();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // An ISR that uses a queue to receive characters to send on a UART.
|
||||||
|
* void vUART_ISR( void )
|
||||||
|
* {
|
||||||
|
* char cCharToTx;
|
||||||
|
* BaseType_t xCRWokenByPost = pdFALSE;
|
||||||
|
*
|
||||||
|
* while( UART_TX_REG_EMPTY() )
|
||||||
|
* {
|
||||||
|
* // Are there any characters in the queue waiting to be sent?
|
||||||
|
* // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
|
||||||
|
* // is woken by the post - ensuring that only a single co-routine is
|
||||||
|
* // woken no matter how many times we go around this loop.
|
||||||
|
* if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
|
||||||
|
* {
|
||||||
|
* SEND_CHARACTER( cCharToTx );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
|
||||||
|
* \ingroup Tasks
|
||||||
|
*/
|
||||||
|
#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) \
|
||||||
|
xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is intended for internal use by the co-routine macros only.
|
||||||
|
* The macro nature of the co-routine implementation requires that the
|
||||||
|
* prototype appears here. The function should not be used by application
|
||||||
|
* writers.
|
||||||
|
*
|
||||||
|
* Removes the current co-routine from its ready list and places it in the
|
||||||
|
* appropriate delayed list.
|
||||||
|
*/
|
||||||
|
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
|
||||||
|
List_t * pxEventList );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is intended for internal use by the queue implementation only.
|
||||||
|
* The function should not be used by application writers.
|
||||||
|
*
|
||||||
|
* Removes the highest priority co-routine from the event list and places it in
|
||||||
|
* the pending ready list.
|
||||||
|
*/
|
||||||
|
BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function resets the internal state of the coroutine module. It must be
|
||||||
|
* called by the application before restarting the scheduler.
|
||||||
|
*/
|
||||||
|
void vCoRoutineResetState( void ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* CO_ROUTINE_H */
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEPRECATED_DEFINITIONS_H
|
||||||
|
#define DEPRECATED_DEFINITIONS_H
|
||||||
|
|
||||||
|
|
||||||
|
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
|
||||||
|
* pre-processor definition was used to ensure the pre-processor found the correct
|
||||||
|
* portmacro.h file for the port being used. That scheme was deprecated in favour
|
||||||
|
* of setting the compiler's include path such that it found the correct
|
||||||
|
* portmacro.h file - removing the need for the constant and allowing the
|
||||||
|
* portmacro.h file to be located anywhere in relation to the port being used. The
|
||||||
|
* definitions below remain in the code for backward compatibility only. New
|
||||||
|
* projects should not use them. */
|
||||||
|
|
||||||
|
#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
|
||||||
|
#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
|
||||||
|
typedef void ( __interrupt __far * pxISR )();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
|
||||||
|
#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
|
||||||
|
typedef void ( __interrupt __far * pxISR )();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_MEGA_AVR
|
||||||
|
#include "../portable/GCC/ATMega323/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IAR_MEGA_AVR
|
||||||
|
#include "../portable/IAR/ATMega323/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MPLAB_PIC24_PORT
|
||||||
|
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MPLAB_DSPIC_PORT
|
||||||
|
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MPLAB_PIC18F_PORT
|
||||||
|
#include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MPLAB_PIC32MX_PORT
|
||||||
|
#include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _FEDPICC
|
||||||
|
#include "libFreeRTOS/Include/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SDCC_CYGNAL
|
||||||
|
#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_ARM7
|
||||||
|
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_ARM7_ECLIPSE
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ROWLEY_LPC23xx
|
||||||
|
#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IAR_MSP430
|
||||||
|
#include "..\..\Source\portable\IAR\MSP430\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_MSP430
|
||||||
|
#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ROWLEY_MSP430
|
||||||
|
#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ARM7_LPC21xx_KEIL_RVDS
|
||||||
|
#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SAM7_GCC
|
||||||
|
#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SAM7_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SAM9XE_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LPC2000_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STR71X_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\STR71x\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STR75X_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\STR75x\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STR75X_GCC
|
||||||
|
#include "..\..\Source\portable\GCC\STR75x\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STR91X_IAR
|
||||||
|
#include "..\..\Source\portable\IAR\STR91x\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_H8S
|
||||||
|
#include "../../Source/portable/GCC/H8S2329/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_AT91FR40008
|
||||||
|
#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RVDS_ARMCM3_LM3S102
|
||||||
|
#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_ARMCM3_LM3S102
|
||||||
|
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_ARMCM3
|
||||||
|
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IAR_ARM_CM3
|
||||||
|
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IAR_ARMCM3_LM
|
||||||
|
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HCS12_CODE_WARRIOR
|
||||||
|
#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MICROBLAZE_GCC
|
||||||
|
#include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TERN_EE
|
||||||
|
#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_HCS12
|
||||||
|
#include "../../Source/portable/GCC/HCS12/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_MCF5235
|
||||||
|
#include "../../Source/portable/GCC/MCF5235/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef COLDFIRE_V2_GCC
|
||||||
|
#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef COLDFIRE_V2_CODEWARRIOR
|
||||||
|
#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_PPC405
|
||||||
|
#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_PPC440
|
||||||
|
#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _16FX_SOFTUNE
|
||||||
|
#include "..\..\Source\portable\Softune\MB96340\portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BCC_INDUSTRIAL_PC_PORT
|
||||||
|
|
||||||
|
/* A short file name has to be used in place of the normal
|
||||||
|
* FreeRTOSConfig.h when using the Borland compiler. */
|
||||||
|
#include "frconfig.h"
|
||||||
|
#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
|
||||||
|
typedef void ( __interrupt __far * pxISR )();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BCC_FLASH_LITE_186_PORT
|
||||||
|
|
||||||
|
/* A short file name has to be used in place of the normal
|
||||||
|
* FreeRTOSConfig.h when using the Borland compiler. */
|
||||||
|
#include "frconfig.h"
|
||||||
|
#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
|
||||||
|
typedef void ( __interrupt __far * pxISR )();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#ifdef __AVR32_AVR32A__
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ICCAVR32__
|
||||||
|
#ifdef __CORE__
|
||||||
|
#if __CORE__ == __AVR32A__
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __91467D
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __96340
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __IAR_V850ES_Fx3__
|
||||||
|
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_V850ES_Jx3__
|
||||||
|
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_V850ES_Jx3_L__
|
||||||
|
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_V850ES_Jx2__
|
||||||
|
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_V850ES_Hx2__
|
||||||
|
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_78K0R_Kx3__
|
||||||
|
#include "../../Source/portable/IAR/78K0R/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __IAR_78K0R_Kx3L__
|
||||||
|
#include "../../Source/portable/IAR/78K0R/portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DEPRECATED_DEFINITIONS_H */
|
||||||
@@ -0,0 +1,848 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EVENT_GROUPS_H
|
||||||
|
#define EVENT_GROUPS_H
|
||||||
|
|
||||||
|
#ifndef INC_FREERTOS_H
|
||||||
|
#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* FreeRTOS includes. */
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
|
/* The following bit fields convey control information in a task's event list
|
||||||
|
* item value. It is important they don't clash with the
|
||||||
|
* taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
|
||||||
|
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||||
|
#define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint16_t ) 0x0100U )
|
||||||
|
#define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint16_t ) 0x0200U )
|
||||||
|
#define eventWAIT_FOR_ALL_BITS ( ( uint16_t ) 0x0400U )
|
||||||
|
#define eventEVENT_BITS_CONTROL_BYTES ( ( uint16_t ) 0xff00U )
|
||||||
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||||
|
#define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint32_t ) 0x01000000U )
|
||||||
|
#define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint32_t ) 0x02000000U )
|
||||||
|
#define eventWAIT_FOR_ALL_BITS ( ( uint32_t ) 0x04000000U )
|
||||||
|
#define eventEVENT_BITS_CONTROL_BYTES ( ( uint32_t ) 0xff000000U )
|
||||||
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS )
|
||||||
|
#define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint64_t ) 0x0100000000000000U )
|
||||||
|
#define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint64_t ) 0x0200000000000000U )
|
||||||
|
#define eventWAIT_FOR_ALL_BITS ( ( uint64_t ) 0x0400000000000000U )
|
||||||
|
#define eventEVENT_BITS_CONTROL_BYTES ( ( uint64_t ) 0xff00000000000000U )
|
||||||
|
#endif /* if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) */
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event group is a collection of bits to which an application can assign a
|
||||||
|
* meaning. For example, an application may create an event group to convey
|
||||||
|
* the status of various CAN bus related events in which bit 0 might mean "A CAN
|
||||||
|
* message has been received and is ready for processing", bit 1 might mean "The
|
||||||
|
* application has queued a message that is ready for sending onto the CAN
|
||||||
|
* network", and bit 2 might mean "It is time to send a SYNC message onto the
|
||||||
|
* CAN network" etc. A task can then test the bit values to see which events
|
||||||
|
* are active, and optionally enter the Blocked state to wait for a specified
|
||||||
|
* bit or a group of specified bits to be active. To continue the CAN bus
|
||||||
|
* example, a CAN controlling task can enter the Blocked state (and therefore
|
||||||
|
* not consume any processing time) until either bit 0, bit 1 or bit 2 are
|
||||||
|
* active, at which time the bit that was actually active would inform the task
|
||||||
|
* which action it had to take (process a received message, send a message, or
|
||||||
|
* send a SYNC).
|
||||||
|
*
|
||||||
|
* The event groups implementation contains intelligence to avoid race
|
||||||
|
* conditions that would otherwise occur were an application to use a simple
|
||||||
|
* variable for the same purpose. This is particularly important with respect
|
||||||
|
* to when a bit within an event group is to be cleared, and when bits have to
|
||||||
|
* be set and then tested atomically - as is the case where event groups are
|
||||||
|
* used to create a synchronisation point between multiple tasks (a
|
||||||
|
* 'rendezvous').
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
*
|
||||||
|
* Type by which event groups are referenced. For example, a call to
|
||||||
|
* xEventGroupCreate() returns an EventGroupHandle_t variable that can then
|
||||||
|
* be used as a parameter to other event group functions.
|
||||||
|
*
|
||||||
|
* \defgroup EventGroupHandle_t EventGroupHandle_t
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
struct EventGroupDef_t;
|
||||||
|
typedef struct EventGroupDef_t * EventGroupHandle_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The type that holds event bits always matches TickType_t - therefore the
|
||||||
|
* number of bits it holds is set by configTICK_TYPE_WIDTH_IN_BITS (16 bits if set to 0,
|
||||||
|
* 32 bits if set to 1, 64 bits if set to 2.
|
||||||
|
*
|
||||||
|
* \defgroup EventBits_t EventBits_t
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
typedef TickType_t EventBits_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* EventGroupHandle_t xEventGroupCreate( void );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Create a new event group.
|
||||||
|
*
|
||||||
|
* Internally, within the FreeRTOS implementation, event groups use a [small]
|
||||||
|
* block of memory, in which the event group's structure is stored. If an event
|
||||||
|
* groups is created using xEventGroupCreate() then the required memory is
|
||||||
|
* automatically dynamically allocated inside the xEventGroupCreate() function.
|
||||||
|
* (see https://www.FreeRTOS.org/a00111.html). If an event group is created
|
||||||
|
* using xEventGroupCreateStatic() then the application writer must instead
|
||||||
|
* provide the memory that will get used by the event group.
|
||||||
|
* xEventGroupCreateStatic() therefore allows an event group to be created
|
||||||
|
* without using any dynamic memory allocation.
|
||||||
|
*
|
||||||
|
* Although event groups are not related to ticks, for internal implementation
|
||||||
|
* reasons the number of bits available for use in an event group is dependent
|
||||||
|
* on the configTICK_TYPE_WIDTH_IN_BITS setting in FreeRTOSConfig.h. If
|
||||||
|
* configTICK_TYPE_WIDTH_IN_BITS is 0 then each event group contains 8 usable bits (bit
|
||||||
|
* 0 to bit 7). If configTICK_TYPE_WIDTH_IN_BITS is set to 1 then each event group has
|
||||||
|
* 24 usable bits (bit 0 to bit 23). If configTICK_TYPE_WIDTH_IN_BITS is set to 2 then
|
||||||
|
* each event group has 56 usable bits (bit 0 to bit 53). The EventBits_t type
|
||||||
|
* is used to store event bits within an event group.
|
||||||
|
*
|
||||||
|
* The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupCreate()
|
||||||
|
* to be available.
|
||||||
|
*
|
||||||
|
* @return If the event group was created then a handle to the event group is
|
||||||
|
* returned. If there was insufficient FreeRTOS heap available to create the
|
||||||
|
* event group then NULL is returned. See https://www.FreeRTOS.org/a00111.html
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // Declare a variable to hold the created event group.
|
||||||
|
* EventGroupHandle_t xCreatedEventGroup;
|
||||||
|
*
|
||||||
|
* // Attempt to create the event group.
|
||||||
|
* xCreatedEventGroup = xEventGroupCreate();
|
||||||
|
*
|
||||||
|
* // Was the event group created successfully?
|
||||||
|
* if( xCreatedEventGroup == NULL )
|
||||||
|
* {
|
||||||
|
* // The event group was not created because there was insufficient
|
||||||
|
* // FreeRTOS heap available.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // The event group was created.
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xEventGroupCreate xEventGroupCreate
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
|
EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Create a new event group.
|
||||||
|
*
|
||||||
|
* Internally, within the FreeRTOS implementation, event groups use a [small]
|
||||||
|
* block of memory, in which the event group's structure is stored. If an event
|
||||||
|
* groups is created using xEventGroupCreate() then the required memory is
|
||||||
|
* automatically dynamically allocated inside the xEventGroupCreate() function.
|
||||||
|
* (see https://www.FreeRTOS.org/a00111.html). If an event group is created
|
||||||
|
* using xEventGroupCreateStatic() then the application writer must instead
|
||||||
|
* provide the memory that will get used by the event group.
|
||||||
|
* xEventGroupCreateStatic() therefore allows an event group to be created
|
||||||
|
* without using any dynamic memory allocation.
|
||||||
|
*
|
||||||
|
* Although event groups are not related to ticks, for internal implementation
|
||||||
|
* reasons the number of bits available for use in an event group is dependent
|
||||||
|
* on the configTICK_TYPE_WIDTH_IN_BITS setting in FreeRTOSConfig.h. If
|
||||||
|
* configTICK_TYPE_WIDTH_IN_BITS is 0 then each event group contains 8 usable bits (bit
|
||||||
|
* 0 to bit 7). If configTICK_TYPE_WIDTH_IN_BITS is set to 1 then each event group has
|
||||||
|
* 24 usable bits (bit 0 to bit 23). If configTICK_TYPE_WIDTH_IN_BITS is set to 2 then
|
||||||
|
* each event group has 56 usable bits (bit 0 to bit 53). The EventBits_t type
|
||||||
|
* is used to store event bits within an event group.
|
||||||
|
*
|
||||||
|
* The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupCreateStatic()
|
||||||
|
* to be available.
|
||||||
|
*
|
||||||
|
* @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type
|
||||||
|
* StaticEventGroup_t, which will be then be used to hold the event group's data
|
||||||
|
* structures, removing the need for the memory to be allocated dynamically.
|
||||||
|
*
|
||||||
|
* @return If the event group was created then a handle to the event group is
|
||||||
|
* returned. If pxEventGroupBuffer was NULL then NULL is returned.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // StaticEventGroup_t is a publicly accessible structure that has the same
|
||||||
|
* // size and alignment requirements as the real event group structure. It is
|
||||||
|
* // provided as a mechanism for applications to know the size of the event
|
||||||
|
* // group (which is dependent on the architecture and configuration file
|
||||||
|
* // settings) without breaking the strict data hiding policy by exposing the
|
||||||
|
* // real event group internals. This StaticEventGroup_t variable is passed
|
||||||
|
* // into the xSemaphoreCreateEventGroupStatic() function and is used to store
|
||||||
|
* // the event group's data structures
|
||||||
|
* StaticEventGroup_t xEventGroupBuffer;
|
||||||
|
*
|
||||||
|
* // Create the event group without dynamically allocating any memory.
|
||||||
|
* xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||||
|
* const EventBits_t uxBitsToWaitFor,
|
||||||
|
* const BaseType_t xClearOnExit,
|
||||||
|
* const BaseType_t xWaitForAllBits,
|
||||||
|
* const TickType_t xTicksToWait );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* [Potentially] block to wait for one or more bits to be set within a
|
||||||
|
* previously created event group.
|
||||||
|
*
|
||||||
|
* This function cannot be called from an interrupt.
|
||||||
|
*
|
||||||
|
* The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupWaitBits()
|
||||||
|
* to be available.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are being tested. The
|
||||||
|
* event group must have previously been created using a call to
|
||||||
|
* xEventGroupCreate().
|
||||||
|
*
|
||||||
|
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
|
||||||
|
* inside the event group. For example, to wait for bit 0 and/or bit 2 set
|
||||||
|
* uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set
|
||||||
|
* uxBitsToWaitFor to 0x07. Etc.
|
||||||
|
*
|
||||||
|
* @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within
|
||||||
|
* uxBitsToWaitFor that are set within the event group will be cleared before
|
||||||
|
* xEventGroupWaitBits() returns if the wait condition was met (if the function
|
||||||
|
* returns for a reason other than a timeout). If xClearOnExit is set to
|
||||||
|
* pdFALSE then the bits set in the event group are not altered when the call to
|
||||||
|
* xEventGroupWaitBits() returns.
|
||||||
|
*
|
||||||
|
* @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then
|
||||||
|
* xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor
|
||||||
|
* are set or the specified block time expires. If xWaitForAllBits is set to
|
||||||
|
* pdFALSE then xEventGroupWaitBits() will return when any one of the bits set
|
||||||
|
* in uxBitsToWaitFor is set or the specified block time expires. The block
|
||||||
|
* time is specified by the xTicksToWait parameter.
|
||||||
|
*
|
||||||
|
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
|
||||||
|
* for one/all (depending on the xWaitForAllBits value) of the bits specified by
|
||||||
|
* uxBitsToWaitFor to become set. A value of portMAX_DELAY can be used to block
|
||||||
|
* indefinitely (provided INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h).
|
||||||
|
*
|
||||||
|
* @return The value of the event group at the time either the bits being waited
|
||||||
|
* for became set, or the block time expired. Test the return value to know
|
||||||
|
* which bits were set. If xEventGroupWaitBits() returned because its timeout
|
||||||
|
* expired then not all the bits being waited for will be set. If
|
||||||
|
* xEventGroupWaitBits() returned because the bits it was waiting for were set
|
||||||
|
* then the returned value is the event group value before any bits were
|
||||||
|
* automatically cleared in the case that xClearOnExit parameter was set to
|
||||||
|
* pdTRUE.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* #define BIT_0 ( 1 << 0 )
|
||||||
|
* #define BIT_4 ( 1 << 4 )
|
||||||
|
*
|
||||||
|
* void aFunction( EventGroupHandle_t xEventGroup )
|
||||||
|
* {
|
||||||
|
* EventBits_t uxBits;
|
||||||
|
* const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
|
||||||
|
*
|
||||||
|
* // Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
|
||||||
|
* // the event group. Clear the bits before exiting.
|
||||||
|
* uxBits = xEventGroupWaitBits(
|
||||||
|
* xEventGroup, // The event group being tested.
|
||||||
|
* BIT_0 | BIT_4, // The bits within the event group to wait for.
|
||||||
|
* pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
|
||||||
|
* pdFALSE, // Don't wait for both bits, either bit will do.
|
||||||
|
* xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
|
||||||
|
*
|
||||||
|
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||||
|
* {
|
||||||
|
* // xEventGroupWaitBits() returned because both bits were set.
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_0 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // xEventGroupWaitBits() returned because just BIT_0 was set.
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_4 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // xEventGroupWaitBits() returned because just BIT_4 was set.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // xEventGroupWaitBits() returned because xTicksToWait ticks passed
|
||||||
|
* // without either BIT_0 or BIT_4 becoming set.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xEventGroupWaitBits xEventGroupWaitBits
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
const BaseType_t xClearOnExit,
|
||||||
|
const BaseType_t xWaitForAllBits,
|
||||||
|
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Clear bits within an event group. This function cannot be called from an
|
||||||
|
* interrupt.
|
||||||
|
*
|
||||||
|
* The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupClearBits()
|
||||||
|
* to be available.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are to be cleared.
|
||||||
|
*
|
||||||
|
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear
|
||||||
|
* in the event group. For example, to clear bit 3 only, set uxBitsToClear to
|
||||||
|
* 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09.
|
||||||
|
*
|
||||||
|
* @return The value of the event group before the specified bits were cleared.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* #define BIT_0 ( 1 << 0 )
|
||||||
|
* #define BIT_4 ( 1 << 4 )
|
||||||
|
*
|
||||||
|
* void aFunction( EventGroupHandle_t xEventGroup )
|
||||||
|
* {
|
||||||
|
* EventBits_t uxBits;
|
||||||
|
*
|
||||||
|
* // Clear bit 0 and bit 4 in xEventGroup.
|
||||||
|
* uxBits = xEventGroupClearBits(
|
||||||
|
* xEventGroup, // The event group being updated.
|
||||||
|
* BIT_0 | BIT_4 );// The bits being cleared.
|
||||||
|
*
|
||||||
|
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||||
|
* {
|
||||||
|
* // Both bit 0 and bit 4 were set before xEventGroupClearBits() was
|
||||||
|
* // called. Both will now be clear (not set).
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_0 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // Bit 0 was set before xEventGroupClearBits() was called. It will
|
||||||
|
* // now be clear.
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_4 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // Bit 4 was set before xEventGroupClearBits() was called. It will
|
||||||
|
* // now be clear.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // Neither bit 0 nor bit 4 were set in the first place.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xEventGroupClearBits xEventGroupClearBits
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* A version of xEventGroupClearBits() that can be called from an interrupt.
|
||||||
|
*
|
||||||
|
* Setting bits in an event group is not a deterministic operation because there
|
||||||
|
* are an unknown number of tasks that may be waiting for the bit or bits being
|
||||||
|
* set. FreeRTOS does not allow nondeterministic operations to be performed
|
||||||
|
* while interrupts are disabled, so protects event groups that are accessed
|
||||||
|
* from tasks by suspending the scheduler rather than disabling interrupts. As
|
||||||
|
* a result event groups cannot be accessed directly from an interrupt service
|
||||||
|
* routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
|
||||||
|
* timer task to have the clear operation performed in the context of the timer
|
||||||
|
* task.
|
||||||
|
*
|
||||||
|
* @note If this function returns pdPASS then the timer task is ready to run
|
||||||
|
* and a portYIELD_FROM_ISR(pdTRUE) should be executed to perform the needed
|
||||||
|
* clear on the event group. This behavior is different from
|
||||||
|
* xEventGroupSetBitsFromISR because the parameter xHigherPriorityTaskWoken is
|
||||||
|
* not present.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are to be cleared.
|
||||||
|
*
|
||||||
|
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear.
|
||||||
|
* For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3
|
||||||
|
* and bit 0 set uxBitsToClear to 0x09.
|
||||||
|
*
|
||||||
|
* @return If the request to execute the function was posted successfully then
|
||||||
|
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
|
||||||
|
* if the timer service queue was full.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* #define BIT_0 ( 1 << 0 )
|
||||||
|
* #define BIT_4 ( 1 << 4 )
|
||||||
|
*
|
||||||
|
* // An event group which it is assumed has already been created by a call to
|
||||||
|
* // xEventGroupCreate().
|
||||||
|
* EventGroupHandle_t xEventGroup;
|
||||||
|
*
|
||||||
|
* void anInterruptHandler( void )
|
||||||
|
* {
|
||||||
|
* // Clear bit 0 and bit 4 in xEventGroup.
|
||||||
|
* xResult = xEventGroupClearBitsFromISR(
|
||||||
|
* xEventGroup, // The event group being updated.
|
||||||
|
* BIT_0 | BIT_4 ); // The bits being set.
|
||||||
|
*
|
||||||
|
* if( xResult == pdPASS )
|
||||||
|
* {
|
||||||
|
* // The message was posted successfully.
|
||||||
|
* portYIELD_FROM_ISR(pdTRUE);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
#if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||||
|
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif /* if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Set bits within an event group.
|
||||||
|
* This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
|
||||||
|
* is a version that can be called from an interrupt.
|
||||||
|
*
|
||||||
|
* Setting bits in an event group will automatically unblock tasks that are
|
||||||
|
* blocked waiting for the bits.
|
||||||
|
*
|
||||||
|
* The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupSetBits()
|
||||||
|
* to be available.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are to be set.
|
||||||
|
*
|
||||||
|
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
|
||||||
|
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
|
||||||
|
* and bit 0 set uxBitsToSet to 0x09.
|
||||||
|
*
|
||||||
|
* @return The value of the event group at the time the call to
|
||||||
|
* xEventGroupSetBits() returns. Returned value might have the bits specified
|
||||||
|
* by the uxBitsToSet parameter cleared if setting a bit results in a task
|
||||||
|
* that was waiting for the bit leaving the blocked state then it is possible
|
||||||
|
* the bit will be cleared automatically (see the xClearBitOnExit parameter
|
||||||
|
* of xEventGroupWaitBits()).
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* #define BIT_0 ( 1 << 0 )
|
||||||
|
* #define BIT_4 ( 1 << 4 )
|
||||||
|
*
|
||||||
|
* void aFunction( EventGroupHandle_t xEventGroup )
|
||||||
|
* {
|
||||||
|
* EventBits_t uxBits;
|
||||||
|
*
|
||||||
|
* // Set bit 0 and bit 4 in xEventGroup.
|
||||||
|
* uxBits = xEventGroupSetBits(
|
||||||
|
* xEventGroup, // The event group being updated.
|
||||||
|
* BIT_0 | BIT_4 );// The bits being set.
|
||||||
|
*
|
||||||
|
* if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||||
|
* {
|
||||||
|
* // Both bit 0 and bit 4 remained set when the function returned.
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_0 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // Bit 0 remained set when the function returned, but bit 4 was
|
||||||
|
* // cleared. It might be that bit 4 was cleared automatically as a
|
||||||
|
* // task that was waiting for bit 4 was removed from the Blocked
|
||||||
|
* // state.
|
||||||
|
* }
|
||||||
|
* else if( ( uxBits & BIT_4 ) != 0 )
|
||||||
|
* {
|
||||||
|
* // Bit 4 remained set when the function returned, but bit 0 was
|
||||||
|
* // cleared. It might be that bit 0 was cleared automatically as a
|
||||||
|
* // task that was waiting for bit 0 was removed from the Blocked
|
||||||
|
* // state.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // Neither bit 0 nor bit 4 remained set. It might be that a task
|
||||||
|
* // was waiting for both of the bits to be set, and the bits were
|
||||||
|
* // cleared as the task left the Blocked state.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xEventGroupSetBits xEventGroupSetBits
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* A version of xEventGroupSetBits() that can be called from an interrupt.
|
||||||
|
*
|
||||||
|
* Setting bits in an event group is not a deterministic operation because there
|
||||||
|
* are an unknown number of tasks that may be waiting for the bit or bits being
|
||||||
|
* set. FreeRTOS does not allow nondeterministic operations to be performed in
|
||||||
|
* interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR()
|
||||||
|
* sends a message to the timer task to have the set operation performed in the
|
||||||
|
* context of the timer task - where a scheduler lock is used in place of a
|
||||||
|
* critical section.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are to be set.
|
||||||
|
*
|
||||||
|
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
|
||||||
|
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
|
||||||
|
* and bit 0 set uxBitsToSet to 0x09.
|
||||||
|
*
|
||||||
|
* @param pxHigherPriorityTaskWoken As mentioned above, calling this function
|
||||||
|
* will result in a message being sent to the timer daemon task. If the
|
||||||
|
* priority of the timer daemon task is higher than the priority of the
|
||||||
|
* currently running task (the task the interrupt interrupted) then
|
||||||
|
* *pxHigherPriorityTaskWoken will be set to pdTRUE by
|
||||||
|
* xEventGroupSetBitsFromISR(), indicating that a context switch should be
|
||||||
|
* requested before the interrupt exits. For that reason
|
||||||
|
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
|
||||||
|
* example code below.
|
||||||
|
*
|
||||||
|
* @return If the request to execute the function was posted successfully then
|
||||||
|
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
|
||||||
|
* if the timer service queue was full.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* #define BIT_0 ( 1 << 0 )
|
||||||
|
* #define BIT_4 ( 1 << 4 )
|
||||||
|
*
|
||||||
|
* // An event group which it is assumed has already been created by a call to
|
||||||
|
* // xEventGroupCreate().
|
||||||
|
* EventGroupHandle_t xEventGroup;
|
||||||
|
*
|
||||||
|
* void anInterruptHandler( void )
|
||||||
|
* {
|
||||||
|
* BaseType_t xHigherPriorityTaskWoken, xResult;
|
||||||
|
*
|
||||||
|
* // xHigherPriorityTaskWoken must be initialised to pdFALSE.
|
||||||
|
* xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
*
|
||||||
|
* // Set bit 0 and bit 4 in xEventGroup.
|
||||||
|
* xResult = xEventGroupSetBitsFromISR(
|
||||||
|
* xEventGroup, // The event group being updated.
|
||||||
|
* BIT_0 | BIT_4 // The bits being set.
|
||||||
|
* &xHigherPriorityTaskWoken );
|
||||||
|
*
|
||||||
|
* // Was the message posted successfully?
|
||||||
|
* if( xResult == pdPASS )
|
||||||
|
* {
|
||||||
|
* // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
|
||||||
|
* // switch should be requested. The macro used is port specific and
|
||||||
|
* // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
|
||||||
|
* // refer to the documentation page for the port being used.
|
||||||
|
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
#if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||||
|
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet,
|
||||||
|
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif /* if ( ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||||
|
* const EventBits_t uxBitsToSet,
|
||||||
|
* const EventBits_t uxBitsToWaitFor,
|
||||||
|
* TickType_t xTicksToWait );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Atomically set bits within an event group, then wait for a combination of
|
||||||
|
* bits to be set within the same event group. This functionality is typically
|
||||||
|
* used to synchronise multiple tasks, where each task has to wait for the other
|
||||||
|
* tasks to reach a synchronisation point before proceeding.
|
||||||
|
*
|
||||||
|
* This function cannot be used from an interrupt.
|
||||||
|
*
|
||||||
|
* The function will return before its block time expires if the bits specified
|
||||||
|
* by the uxBitsToWait parameter are set, or become set within that time. In
|
||||||
|
* this case all the bits specified by uxBitsToWait will be automatically
|
||||||
|
* cleared before the function returns.
|
||||||
|
*
|
||||||
|
* The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupSync()
|
||||||
|
* to be available.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group in which the bits are being tested. The
|
||||||
|
* event group must have previously been created using a call to
|
||||||
|
* xEventGroupCreate().
|
||||||
|
*
|
||||||
|
* @param uxBitsToSet The bits to set in the event group before determining
|
||||||
|
* if, and possibly waiting for, all the bits specified by the uxBitsToWait
|
||||||
|
* parameter are set.
|
||||||
|
*
|
||||||
|
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
|
||||||
|
* inside the event group. For example, to wait for bit 0 and bit 2 set
|
||||||
|
* uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set
|
||||||
|
* uxBitsToWaitFor to 0x07. Etc.
|
||||||
|
*
|
||||||
|
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
|
||||||
|
* for all of the bits specified by uxBitsToWaitFor to become set.
|
||||||
|
*
|
||||||
|
* @return The value of the event group at the time either the bits being waited
|
||||||
|
* for became set, or the block time expired. Test the return value to know
|
||||||
|
* which bits were set. If xEventGroupSync() returned because its timeout
|
||||||
|
* expired then not all the bits being waited for will be set. If
|
||||||
|
* xEventGroupSync() returned because all the bits it was waiting for were
|
||||||
|
* set then the returned value is the event group value before any bits were
|
||||||
|
* automatically cleared.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
* // Bits used by the three tasks.
|
||||||
|
* #define TASK_0_BIT ( 1 << 0 )
|
||||||
|
* #define TASK_1_BIT ( 1 << 1 )
|
||||||
|
* #define TASK_2_BIT ( 1 << 2 )
|
||||||
|
*
|
||||||
|
* #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
|
||||||
|
*
|
||||||
|
* // Use an event group to synchronise three tasks. It is assumed this event
|
||||||
|
* // group has already been created elsewhere.
|
||||||
|
* EventGroupHandle_t xEventBits;
|
||||||
|
*
|
||||||
|
* void vTask0( void *pvParameters )
|
||||||
|
* {
|
||||||
|
* EventBits_t uxReturn;
|
||||||
|
* TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
|
||||||
|
*
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Perform task functionality here.
|
||||||
|
*
|
||||||
|
* // Set bit 0 in the event flag to note this task has reached the
|
||||||
|
* // sync point. The other two tasks will set the other two bits defined
|
||||||
|
* // by ALL_SYNC_BITS. All three tasks have reached the synchronisation
|
||||||
|
* // point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms
|
||||||
|
* // for this to happen.
|
||||||
|
* uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
|
||||||
|
*
|
||||||
|
* if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
|
||||||
|
* {
|
||||||
|
* // All three tasks reached the synchronisation point before the call
|
||||||
|
* // to xEventGroupSync() timed out.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* void vTask1( void *pvParameters )
|
||||||
|
* {
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Perform task functionality here.
|
||||||
|
*
|
||||||
|
* // Set bit 1 in the event flag to note this task has reached the
|
||||||
|
* // synchronisation point. The other two tasks will set the other two
|
||||||
|
* // bits defined by ALL_SYNC_BITS. All three tasks have reached the
|
||||||
|
* // synchronisation point when all the ALL_SYNC_BITS are set. Wait
|
||||||
|
* // indefinitely for this to happen.
|
||||||
|
* xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
|
||||||
|
*
|
||||||
|
* // xEventGroupSync() was called with an indefinite block time, so
|
||||||
|
* // this task will only reach here if the synchronisation was made by all
|
||||||
|
* // three tasks, so there is no need to test the return value.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* void vTask2( void *pvParameters )
|
||||||
|
* {
|
||||||
|
* for( ;; )
|
||||||
|
* {
|
||||||
|
* // Perform task functionality here.
|
||||||
|
*
|
||||||
|
* // Set bit 2 in the event flag to note this task has reached the
|
||||||
|
* // synchronisation point. The other two tasks will set the other two
|
||||||
|
* // bits defined by ALL_SYNC_BITS. All three tasks have reached the
|
||||||
|
* // synchronisation point when all the ALL_SYNC_BITS are set. Wait
|
||||||
|
* // indefinitely for this to happen.
|
||||||
|
* xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
|
||||||
|
*
|
||||||
|
* // xEventGroupSync() was called with an indefinite block time, so
|
||||||
|
* // this task will only reach here if the synchronisation was made by all
|
||||||
|
* // three tasks, so there is no need to test the return value.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xEventGroupSync xEventGroupSync
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Returns the current value of the bits in an event group. This function
|
||||||
|
* cannot be used from an interrupt.
|
||||||
|
*
|
||||||
|
* The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupGetBits()
|
||||||
|
* to be available.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group being queried.
|
||||||
|
*
|
||||||
|
* @return The event group bits at the time xEventGroupGetBits() was called.
|
||||||
|
*
|
||||||
|
* \defgroup xEventGroupGetBits xEventGroupGetBits
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( ( xEventGroup ), 0 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* A version of xEventGroupGetBits() that can be called from an ISR.
|
||||||
|
*
|
||||||
|
* The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupGetBitsFromISR()
|
||||||
|
* to be available.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group being queried.
|
||||||
|
*
|
||||||
|
* @return The event group bits at the time xEventGroupGetBitsFromISR() was called.
|
||||||
|
*
|
||||||
|
* \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR
|
||||||
|
* \ingroup EventGroup
|
||||||
|
*/
|
||||||
|
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* void xEventGroupDelete( EventGroupHandle_t xEventGroup );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Delete an event group that was previously created by a call to
|
||||||
|
* xEventGroupCreate(). Tasks that are blocked on the event group will be
|
||||||
|
* unblocked and obtain 0 as the event group's value.
|
||||||
|
*
|
||||||
|
* The configUSE_EVENT_GROUPS configuration constant must be set to 1 for vEventGroupDelete()
|
||||||
|
* to be available.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group being deleted.
|
||||||
|
*/
|
||||||
|
void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event_groups.h
|
||||||
|
* @code{c}
|
||||||
|
* BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
|
||||||
|
* StaticEventGroup_t ** ppxEventGroupBuffer );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Retrieve a pointer to a statically created event groups's data structure
|
||||||
|
* buffer. It is the same buffer that is supplied at the time of creation.
|
||||||
|
*
|
||||||
|
* The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupGetStaticBuffer()
|
||||||
|
* to be available.
|
||||||
|
*
|
||||||
|
* @param xEventGroup The event group for which to retrieve the buffer.
|
||||||
|
*
|
||||||
|
* @param ppxEventGroupBuffer Used to return a pointer to the event groups's
|
||||||
|
* data structure buffer.
|
||||||
|
*
|
||||||
|
* @return pdTRUE if the buffer was retrieved, pdFALSE otherwise.
|
||||||
|
*/
|
||||||
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
|
||||||
|
StaticEventGroup_t ** ppxEventGroupBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||||
|
|
||||||
|
/* For internal use only. */
|
||||||
|
void vEventGroupSetBitsCallback( void * pvEventGroup,
|
||||||
|
uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
|
||||||
|
void vEventGroupClearBitsCallback( void * pvEventGroup,
|
||||||
|
uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) PRIVILEGED_FUNCTION;
|
||||||
|
void vEventGroupSetNumber( void * xEventGroup,
|
||||||
|
UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* EVENT_GROUPS_H */
|
||||||
@@ -0,0 +1,511 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the list implementation used by the scheduler. While it is tailored
|
||||||
|
* heavily for the schedulers needs, it is also available for use by
|
||||||
|
* application code.
|
||||||
|
*
|
||||||
|
* list_ts can only store pointers to list_item_ts. Each ListItem_t contains a
|
||||||
|
* numeric value (xItemValue). Most of the time the lists are sorted in
|
||||||
|
* ascending item value order.
|
||||||
|
*
|
||||||
|
* Lists are created already containing one list item. The value of this
|
||||||
|
* item is the maximum possible that can be stored, it is therefore always at
|
||||||
|
* the end of the list and acts as a marker. The list member pxHead always
|
||||||
|
* points to this marker - even though it is at the tail of the list. This
|
||||||
|
* is because the tail contains a wrap back pointer to the true head of
|
||||||
|
* the list.
|
||||||
|
*
|
||||||
|
* In addition to it's value, each list item contains a pointer to the next
|
||||||
|
* item in the list (pxNext), a pointer to the list it is in (pxContainer)
|
||||||
|
* and a pointer back to the object that contains it. These later two
|
||||||
|
* pointers are included for efficiency of list manipulation. There is
|
||||||
|
* effectively a two way link between the object containing the list item and
|
||||||
|
* the list item itself.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \page ListIntroduction List Implementation
|
||||||
|
* \ingroup FreeRTOSIntro
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LIST_H
|
||||||
|
#define LIST_H
|
||||||
|
|
||||||
|
#ifndef INC_FREERTOS_H
|
||||||
|
#error "FreeRTOS.h must be included before list.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The list structure members are modified from within interrupts, and therefore
|
||||||
|
* by rights should be declared volatile. However, they are only modified in a
|
||||||
|
* functionally atomic way (within critical sections of with the scheduler
|
||||||
|
* suspended) and are either passed by reference into a function or indexed via
|
||||||
|
* a volatile variable. Therefore, in all use cases tested so far, the volatile
|
||||||
|
* qualifier can be omitted in order to provide a moderate performance
|
||||||
|
* improvement without adversely affecting functional behaviour. The assembly
|
||||||
|
* instructions generated by the IAR, ARM and GCC compilers when the respective
|
||||||
|
* compiler's options were set for maximum optimisation has been inspected and
|
||||||
|
* deemed to be as intended. That said, as compiler technology advances, and
|
||||||
|
* especially if aggressive cross module optimisation is used (a use case that
|
||||||
|
* has not been exercised to any great extend) then it is feasible that the
|
||||||
|
* volatile qualifier will be needed for correct optimisation. It is expected
|
||||||
|
* that a compiler removing essential code because, without the volatile
|
||||||
|
* qualifier on the list structure members and with aggressive cross module
|
||||||
|
* optimisation, the compiler deemed the code unnecessary will result in
|
||||||
|
* complete and obvious failure of the scheduler. If this is ever experienced
|
||||||
|
* then the volatile qualifier can be inserted in the relevant places within the
|
||||||
|
* list structures by simply defining configLIST_VOLATILE to volatile in
|
||||||
|
* FreeRTOSConfig.h (as per the example at the bottom of this comment block).
|
||||||
|
* If configLIST_VOLATILE is not defined then the preprocessor directives below
|
||||||
|
* will simply #define configLIST_VOLATILE away completely.
|
||||||
|
*
|
||||||
|
* To use volatile list structure members then add the following line to
|
||||||
|
* FreeRTOSConfig.h (without the quotes):
|
||||||
|
* "#define configLIST_VOLATILE volatile"
|
||||||
|
*/
|
||||||
|
#ifndef configLIST_VOLATILE
|
||||||
|
#define configLIST_VOLATILE
|
||||||
|
#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/* Macros that can be used to place known values within the list structures,
|
||||||
|
* then check that the known values do not get corrupted during the execution of
|
||||||
|
* the application. These may catch the list data structures being overwritten in
|
||||||
|
* memory. They will not catch data errors caused by incorrect configuration or
|
||||||
|
* use of FreeRTOS.*/
|
||||||
|
#if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
|
||||||
|
/* Define the macros to do nothing. */
|
||||||
|
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
|
||||||
|
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
|
||||||
|
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE
|
||||||
|
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE
|
||||||
|
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
|
||||||
|
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
|
||||||
|
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
|
||||||
|
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
|
||||||
|
#define listTEST_LIST_ITEM_INTEGRITY( pxItem )
|
||||||
|
#define listTEST_LIST_INTEGRITY( pxList )
|
||||||
|
#else /* if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) */
|
||||||
|
/* Define macros that add new members into the list structures. */
|
||||||
|
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1;
|
||||||
|
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2;
|
||||||
|
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1;
|
||||||
|
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2;
|
||||||
|
|
||||||
|
/* Define macros that set the new structure members to known values. */
|
||||||
|
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
|
||||||
|
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
|
||||||
|
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
|
||||||
|
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
|
||||||
|
|
||||||
|
/* Define macros that will assert if one of the structure members does not
|
||||||
|
* contain its expected value. */
|
||||||
|
#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
|
||||||
|
#define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
|
||||||
|
#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition of the only type of object that a list can contain.
|
||||||
|
*/
|
||||||
|
struct xLIST;
|
||||||
|
struct xLIST_ITEM
|
||||||
|
{
|
||||||
|
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
configLIST_VOLATILE TickType_t xItemValue; /**< The value being listed. In most cases this is used to sort the list in ascending order. */
|
||||||
|
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /**< Pointer to the next ListItem_t in the list. */
|
||||||
|
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /**< Pointer to the previous ListItem_t in the list. */
|
||||||
|
void * pvOwner; /**< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
|
||||||
|
struct xLIST * configLIST_VOLATILE pxContainer; /**< Pointer to the list in which this list item is placed (if any). */
|
||||||
|
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
};
|
||||||
|
typedef struct xLIST_ITEM ListItem_t;
|
||||||
|
|
||||||
|
#if ( configUSE_MINI_LIST_ITEM == 1 )
|
||||||
|
struct xMINI_LIST_ITEM
|
||||||
|
{
|
||||||
|
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
configLIST_VOLATILE TickType_t xItemValue;
|
||||||
|
struct xLIST_ITEM * configLIST_VOLATILE pxNext;
|
||||||
|
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
|
||||||
|
};
|
||||||
|
typedef struct xMINI_LIST_ITEM MiniListItem_t;
|
||||||
|
#else
|
||||||
|
typedef struct xLIST_ITEM MiniListItem_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition of the type of queue used by the scheduler.
|
||||||
|
*/
|
||||||
|
typedef struct xLIST
|
||||||
|
{
|
||||||
|
listFIRST_LIST_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
configLIST_VOLATILE UBaseType_t uxNumberOfItems;
|
||||||
|
ListItem_t * configLIST_VOLATILE pxIndex; /**< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
|
||||||
|
MiniListItem_t xListEnd; /**< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
|
||||||
|
listSECOND_LIST_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
} List_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to set the owner of a list item. The owner of a list item
|
||||||
|
* is the object (usually a TCB) that contains the list item.
|
||||||
|
*
|
||||||
|
* \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to get the owner of a list item. The owner of a list item
|
||||||
|
* is the object (usually a TCB) that contains the list item.
|
||||||
|
*
|
||||||
|
* \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to set the value of the list item. In most cases the value is
|
||||||
|
* used to sort the list in ascending order.
|
||||||
|
*
|
||||||
|
* \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to retrieve the value of the list item. The value can
|
||||||
|
* represent anything - for example the priority of a task, or the time at
|
||||||
|
* which a task should be unblocked.
|
||||||
|
*
|
||||||
|
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to retrieve the value of the list item at the head of a given
|
||||||
|
* list.
|
||||||
|
*
|
||||||
|
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the list item at the head of the list.
|
||||||
|
*
|
||||||
|
* \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the next list item.
|
||||||
|
*
|
||||||
|
* \page listGET_NEXT listGET_NEXT
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the list item that marks the end of the list
|
||||||
|
*
|
||||||
|
* \page listGET_END_MARKER listGET_END_MARKER
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to determine if a list contains any items. The macro will
|
||||||
|
* only have the value true if the list is empty.
|
||||||
|
*
|
||||||
|
* \page listLIST_IS_EMPTY listLIST_IS_EMPTY
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access macro to return the number of items in the list.
|
||||||
|
*/
|
||||||
|
#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access function to obtain the owner of the next entry in a list.
|
||||||
|
*
|
||||||
|
* The list member pxIndex is used to walk through a list. Calling
|
||||||
|
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list
|
||||||
|
* and returns that entry's pxOwner parameter. Using multiple calls to this
|
||||||
|
* function it is therefore possible to move through every item contained in
|
||||||
|
* a list.
|
||||||
|
*
|
||||||
|
* The pxOwner parameter of a list item is a pointer to the object that owns
|
||||||
|
* the list item. In the scheduler this is normally a task control block.
|
||||||
|
* The pxOwner parameter effectively creates a two way link between the list
|
||||||
|
* item and its owner.
|
||||||
|
*
|
||||||
|
* @param pxTCB pxTCB is set to the address of the owner of the next list item.
|
||||||
|
* @param pxList The list from which the next item owner is to be returned.
|
||||||
|
*
|
||||||
|
* \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#if ( configNUMBER_OF_CORES == 1 )
|
||||||
|
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
|
||||||
|
do { \
|
||||||
|
List_t * const pxConstList = ( pxList ); \
|
||||||
|
/* Increment the index to the next item and return the item, ensuring */ \
|
||||||
|
/* we don't return the marker used at the end of the list. */ \
|
||||||
|
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
|
||||||
|
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
|
||||||
|
{ \
|
||||||
|
( pxConstList )->pxIndex = ( pxConstList )->xListEnd.pxNext; \
|
||||||
|
} \
|
||||||
|
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
|
||||||
|
} while( 0 )
|
||||||
|
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
||||||
|
|
||||||
|
/* This function is not required in SMP. FreeRTOS SMP scheduler doesn't use
|
||||||
|
* pxIndex and it should always point to the xListEnd. Not defining this macro
|
||||||
|
* here to prevent updating pxIndex.
|
||||||
|
*/
|
||||||
|
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version of uxListRemove() that does not return a value. Provided as a slight
|
||||||
|
* optimisation for xTaskIncrementTick() by being inline.
|
||||||
|
*
|
||||||
|
* Remove an item from a list. The list item has a pointer to the list that
|
||||||
|
* it is in, so only the list item need be passed into the function.
|
||||||
|
*
|
||||||
|
* @param uxListRemove The item to be removed. The item will remove itself from
|
||||||
|
* the list pointed to by it's pxContainer parameter.
|
||||||
|
*
|
||||||
|
* @return The number of items that remain in the list after the list item has
|
||||||
|
* been removed.
|
||||||
|
*
|
||||||
|
* \page listREMOVE_ITEM listREMOVE_ITEM
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listREMOVE_ITEM( pxItemToRemove ) \
|
||||||
|
do { \
|
||||||
|
/* The list item knows which list it is in. Obtain the list from the list \
|
||||||
|
* item. */ \
|
||||||
|
List_t * const pxList = ( pxItemToRemove )->pxContainer; \
|
||||||
|
\
|
||||||
|
( pxItemToRemove )->pxNext->pxPrevious = ( pxItemToRemove )->pxPrevious; \
|
||||||
|
( pxItemToRemove )->pxPrevious->pxNext = ( pxItemToRemove )->pxNext; \
|
||||||
|
/* Make sure the index is left pointing to a valid item. */ \
|
||||||
|
if( pxList->pxIndex == ( pxItemToRemove ) ) \
|
||||||
|
{ \
|
||||||
|
pxList->pxIndex = ( pxItemToRemove )->pxPrevious; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
( pxItemToRemove )->pxContainer = NULL; \
|
||||||
|
( ( pxList )->uxNumberOfItems ) = ( UBaseType_t ) ( ( ( pxList )->uxNumberOfItems ) - 1U ); \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inline version of vListInsertEnd() to provide slight optimisation for
|
||||||
|
* xTaskIncrementTick().
|
||||||
|
*
|
||||||
|
* Insert a list item into a list. The item will be inserted in a position
|
||||||
|
* such that it will be the last item within the list returned by multiple
|
||||||
|
* calls to listGET_OWNER_OF_NEXT_ENTRY.
|
||||||
|
*
|
||||||
|
* The list member pxIndex is used to walk through a list. Calling
|
||||||
|
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
|
||||||
|
* Placing an item in a list using vListInsertEnd effectively places the item
|
||||||
|
* in the list position pointed to by pxIndex. This means that every other
|
||||||
|
* item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
|
||||||
|
* the pxIndex parameter again points to the item being inserted.
|
||||||
|
*
|
||||||
|
* @param pxList The list into which the item is to be inserted.
|
||||||
|
*
|
||||||
|
* @param pxNewListItem The list item to be inserted into the list.
|
||||||
|
*
|
||||||
|
* \page listINSERT_END listINSERT_END
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listINSERT_END( pxList, pxNewListItem ) \
|
||||||
|
do { \
|
||||||
|
ListItem_t * const pxIndex = ( pxList )->pxIndex; \
|
||||||
|
\
|
||||||
|
/* Only effective when configASSERT() is also defined, these tests may catch \
|
||||||
|
* the list data structures being overwritten in memory. They will not catch \
|
||||||
|
* data errors caused by incorrect configuration or use of FreeRTOS. */ \
|
||||||
|
listTEST_LIST_INTEGRITY( ( pxList ) ); \
|
||||||
|
listTEST_LIST_ITEM_INTEGRITY( ( pxNewListItem ) ); \
|
||||||
|
\
|
||||||
|
/* Insert a new list item into ( pxList ), but rather than sort the list, \
|
||||||
|
* makes the new list item the last item to be removed by a call to \
|
||||||
|
* listGET_OWNER_OF_NEXT_ENTRY(). */ \
|
||||||
|
( pxNewListItem )->pxNext = pxIndex; \
|
||||||
|
( pxNewListItem )->pxPrevious = pxIndex->pxPrevious; \
|
||||||
|
\
|
||||||
|
pxIndex->pxPrevious->pxNext = ( pxNewListItem ); \
|
||||||
|
pxIndex->pxPrevious = ( pxNewListItem ); \
|
||||||
|
\
|
||||||
|
/* Remember which list the item is in. */ \
|
||||||
|
( pxNewListItem )->pxContainer = ( pxList ); \
|
||||||
|
\
|
||||||
|
( ( pxList )->uxNumberOfItems ) = ( UBaseType_t ) ( ( ( pxList )->uxNumberOfItems ) + 1U ); \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access function to obtain the owner of the first entry in a list. Lists
|
||||||
|
* are normally sorted in ascending item value order.
|
||||||
|
*
|
||||||
|
* This function returns the pxOwner member of the first item in the list.
|
||||||
|
* The pxOwner parameter of a list item is a pointer to the object that owns
|
||||||
|
* the list item. In the scheduler this is normally a task control block.
|
||||||
|
* The pxOwner parameter effectively creates a two way link between the list
|
||||||
|
* item and its owner.
|
||||||
|
*
|
||||||
|
* @param pxList The list from which the owner of the head item is to be
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( ( &( ( pxList )->xListEnd ) )->pxNext->pvOwner )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if a list item is within a list. The list item maintains a
|
||||||
|
* "container" pointer that points to the list it is in. All this macro does
|
||||||
|
* is check to see if the container and the list match.
|
||||||
|
*
|
||||||
|
* @param pxList The list we want to know if the list item is within.
|
||||||
|
* @param pxListItem The list item we want to know if is in the list.
|
||||||
|
* @return pdTRUE if the list item is in the list, otherwise pdFALSE.
|
||||||
|
*/
|
||||||
|
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the list a list item is contained within (referenced from).
|
||||||
|
*
|
||||||
|
* @param pxListItem The list item being queried.
|
||||||
|
* @return A pointer to the List_t object that references the pxListItem
|
||||||
|
*/
|
||||||
|
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This provides a crude means of knowing if a list has been initialised, as
|
||||||
|
* pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must be called before a list is used! This initialises all the members
|
||||||
|
* of the list structure and inserts the xListEnd item into the list as a
|
||||||
|
* marker to the back of the list.
|
||||||
|
*
|
||||||
|
* @param pxList Pointer to the list being initialised.
|
||||||
|
*
|
||||||
|
* \page vListInitialise vListInitialise
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must be called before a list item is used. This sets the list container to
|
||||||
|
* null so the item does not think that it is already contained in a list.
|
||||||
|
*
|
||||||
|
* @param pxItem Pointer to the list item being initialised.
|
||||||
|
*
|
||||||
|
* \page vListInitialiseItem vListInitialiseItem
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert a list item into a list. The item will be inserted into the list in
|
||||||
|
* a position determined by its item value (ascending item value order).
|
||||||
|
*
|
||||||
|
* @param pxList The list into which the item is to be inserted.
|
||||||
|
*
|
||||||
|
* @param pxNewListItem The item that is to be placed in the list.
|
||||||
|
*
|
||||||
|
* \page vListInsert vListInsert
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
void vListInsert( List_t * const pxList,
|
||||||
|
ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert a list item into a list. The item will be inserted in a position
|
||||||
|
* such that it will be the last item within the list returned by multiple
|
||||||
|
* calls to listGET_OWNER_OF_NEXT_ENTRY.
|
||||||
|
*
|
||||||
|
* The list member pxIndex is used to walk through a list. Calling
|
||||||
|
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
|
||||||
|
* Placing an item in a list using vListInsertEnd effectively places the item
|
||||||
|
* in the list position pointed to by pxIndex. This means that every other
|
||||||
|
* item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
|
||||||
|
* the pxIndex parameter again points to the item being inserted.
|
||||||
|
*
|
||||||
|
* @param pxList The list into which the item is to be inserted.
|
||||||
|
*
|
||||||
|
* @param pxNewListItem The list item to be inserted into the list.
|
||||||
|
*
|
||||||
|
* \page vListInsertEnd vListInsertEnd
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
void vListInsertEnd( List_t * const pxList,
|
||||||
|
ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove an item from a list. The list item has a pointer to the list that
|
||||||
|
* it is in, so only the list item need be passed into the function.
|
||||||
|
*
|
||||||
|
* @param uxListRemove The item to be removed. The item will remove itself from
|
||||||
|
* the list pointed to by it's pxContainer parameter.
|
||||||
|
*
|
||||||
|
* @return The number of items that remain in the list after the list item has
|
||||||
|
* been removed.
|
||||||
|
*
|
||||||
|
* \page uxListRemove uxListRemove
|
||||||
|
* \ingroup LinkedList
|
||||||
|
*/
|
||||||
|
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* ifndef LIST_H */
|
||||||
@@ -0,0 +1,967 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Message buffers build functionality on top of FreeRTOS stream buffers.
|
||||||
|
* Whereas stream buffers are used to send a continuous stream of data from one
|
||||||
|
* task or interrupt to another, message buffers are used to send variable
|
||||||
|
* length discrete messages from one task or interrupt to another. Their
|
||||||
|
* implementation is light weight, making them particularly suited for interrupt
|
||||||
|
* to task and core to core communication scenarios.
|
||||||
|
*
|
||||||
|
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||||
|
* implementation (so also the message buffer implementation, as message buffers
|
||||||
|
* are built on top of stream buffers) assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||||
|
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||||
|
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||||
|
* multiple different readers. If there are to be multiple different writers
|
||||||
|
* then the application writer must serialize calls to writing API functions
|
||||||
|
* (such as xStreamBufferSend()). Likewise, if there are to be multiple
|
||||||
|
* different readers then the application writer must serialize calls to reading
|
||||||
|
* API functions (such as xStreamBufferReceive()). One way to achieve such
|
||||||
|
* serialization in single core or SMP kernel is to place each API call inside a
|
||||||
|
* critical section and use a block time of 0.
|
||||||
|
*
|
||||||
|
* Message buffers hold variable length messages. To enable that, when a
|
||||||
|
* message is written to the message buffer an additional sizeof( size_t ) bytes
|
||||||
|
* are also written to store the message's length (that happens internally, with
|
||||||
|
* the API function). sizeof( size_t ) is typically 4 bytes on a 32-bit
|
||||||
|
* architecture, so writing a 10 byte message to a message buffer on a 32-bit
|
||||||
|
* architecture will actually reduce the available space in the message buffer
|
||||||
|
* by 14 bytes (10 byte are used by the message, and 4 bytes to hold the length
|
||||||
|
* of the message).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FREERTOS_MESSAGE_BUFFER_H
|
||||||
|
#define FREERTOS_MESSAGE_BUFFER_H
|
||||||
|
|
||||||
|
#ifndef INC_FREERTOS_H
|
||||||
|
#error "include FreeRTOS.h must appear in source files before include message_buffer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Message buffers are built onto of stream buffers. */
|
||||||
|
#include "stream_buffer.h"
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#if defined( __cplusplus )
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type by which message buffers are referenced. For example, a call to
|
||||||
|
* xMessageBufferCreate() returns an MessageBufferHandle_t variable that can
|
||||||
|
* then be used as a parameter to xMessageBufferSend(), xMessageBufferReceive(),
|
||||||
|
* etc. Message buffer is essentially built as a stream buffer hence its handle
|
||||||
|
* is also set to same type as a stream buffer handle.
|
||||||
|
*/
|
||||||
|
typedef StreamBufferHandle_t MessageBufferHandle_t;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* @code{c}
|
||||||
|
* MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Creates a new message buffer using dynamically allocated memory. See
|
||||||
|
* xMessageBufferCreateStatic() for a version that uses statically allocated
|
||||||
|
* memory (memory that is allocated at compile time).
|
||||||
|
*
|
||||||
|
* configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in
|
||||||
|
* FreeRTOSConfig.h for xMessageBufferCreate() to be available.
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferCreate() to be available.
|
||||||
|
*
|
||||||
|
* @param xBufferSizeBytes The total number of bytes (not messages) the message
|
||||||
|
* buffer will be able to hold at any one time. When a message is written to
|
||||||
|
* the message buffer an additional sizeof( size_t ) bytes are also written to
|
||||||
|
* store the message's length. sizeof( size_t ) is typically 4 bytes on a
|
||||||
|
* 32-bit architecture, so on most 32-bit architectures a 10 byte message will
|
||||||
|
* take up 14 bytes of message buffer space.
|
||||||
|
*
|
||||||
|
* @param pxSendCompletedCallback Callback invoked when a send operation to the
|
||||||
|
* message buffer is complete. If the parameter is NULL or xMessageBufferCreate()
|
||||||
|
* is called without the parameter, then it will use the default implementation
|
||||||
|
* provided by sbSEND_COMPLETED macro. To enable the callback,
|
||||||
|
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||||
|
*
|
||||||
|
* @param pxReceiveCompletedCallback Callback invoked when a receive operation from
|
||||||
|
* the message buffer is complete. If the parameter is NULL or xMessageBufferCreate()
|
||||||
|
* is called without the parameter, it will use the default implementation provided
|
||||||
|
* by sbRECEIVE_COMPLETED macro. To enable the callback,
|
||||||
|
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||||
|
*
|
||||||
|
* @return If NULL is returned, then the message buffer cannot be created
|
||||||
|
* because there is insufficient heap memory available for FreeRTOS to allocate
|
||||||
|
* the message buffer data structures and storage area. A non-NULL value being
|
||||||
|
* returned indicates that the message buffer has been created successfully -
|
||||||
|
* the returned value should be stored as the handle to the created message
|
||||||
|
* buffer.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* @code{c}
|
||||||
|
*
|
||||||
|
* void vAFunction( void )
|
||||||
|
* {
|
||||||
|
* MessageBufferHandle_t xMessageBuffer;
|
||||||
|
* const size_t xMessageBufferSizeBytes = 100;
|
||||||
|
*
|
||||||
|
* // Create a message buffer that can hold 100 bytes. The memory used to hold
|
||||||
|
* // both the message buffer structure and the messages themselves is allocated
|
||||||
|
* // dynamically. Each message added to the buffer consumes an additional 4
|
||||||
|
* // bytes which are used to hold the length of the message.
|
||||||
|
* xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes );
|
||||||
|
*
|
||||||
|
* if( xMessageBuffer == NULL )
|
||||||
|
* {
|
||||||
|
* // There was not enough heap memory space available to create the
|
||||||
|
* // message buffer.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // The message buffer was created successfully and can now be used.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xMessageBufferCreate xMessageBufferCreate
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferCreate( xBufferSizeBytes ) \
|
||||||
|
xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( size_t ) 0, sbTYPE_MESSAGE_BUFFER, NULL, NULL )
|
||||||
|
|
||||||
|
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
|
||||||
|
#define xMessageBufferCreateWithCallback( xBufferSizeBytes, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
|
||||||
|
xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( size_t ) 0, sbTYPE_MESSAGE_BUFFER, ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* @code{c}
|
||||||
|
* MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes,
|
||||||
|
* uint8_t *pucMessageBufferStorageArea,
|
||||||
|
* StaticMessageBuffer_t *pxStaticMessageBuffer );
|
||||||
|
* @endcode
|
||||||
|
* Creates a new message buffer using statically allocated memory. See
|
||||||
|
* xMessageBufferCreate() for a version that uses dynamically allocated memory.
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferCreateStatic() to be available.
|
||||||
|
*
|
||||||
|
* @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the
|
||||||
|
* pucMessageBufferStorageArea parameter. When a message is written to the
|
||||||
|
* message buffer an additional sizeof( size_t ) bytes are also written to store
|
||||||
|
* the message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
|
||||||
|
* architecture, so on most 32-bit architecture a 10 byte message will take up
|
||||||
|
* 14 bytes of message buffer space. The maximum number of bytes that can be
|
||||||
|
* stored in the message buffer is actually (xBufferSizeBytes - 1).
|
||||||
|
*
|
||||||
|
* @param pucMessageBufferStorageArea Must point to a uint8_t array that is at
|
||||||
|
* least xBufferSizeBytes big. This is the array to which messages are
|
||||||
|
* copied when they are written to the message buffer.
|
||||||
|
*
|
||||||
|
* @param pxStaticMessageBuffer Must point to a variable of type
|
||||||
|
* StaticMessageBuffer_t, which will be used to hold the message buffer's data
|
||||||
|
* structure.
|
||||||
|
*
|
||||||
|
* @param pxSendCompletedCallback Callback invoked when a new message is sent to the message buffer.
|
||||||
|
* If the parameter is NULL or xMessageBufferCreate() is called without the parameter, then it will use the default
|
||||||
|
* implementation provided by sbSEND_COMPLETED macro. To enable the callback,
|
||||||
|
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||||
|
*
|
||||||
|
* @param pxReceiveCompletedCallback Callback invoked when a message is read from a
|
||||||
|
* message buffer. If the parameter is NULL or xMessageBufferCreate() is called without the parameter, it will
|
||||||
|
* use the default implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback,
|
||||||
|
* configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
|
||||||
|
*
|
||||||
|
* @return If the message buffer is created successfully then a handle to the
|
||||||
|
* created message buffer is returned. If either pucMessageBufferStorageArea or
|
||||||
|
* pxStaticmessageBuffer are NULL then NULL is returned.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* @code{c}
|
||||||
|
*
|
||||||
|
* // Used to dimension the array used to hold the messages. The available space
|
||||||
|
* // will actually be one less than this, so 999.
|
||||||
|
#define STORAGE_SIZE_BYTES 1000
|
||||||
|
*
|
||||||
|
* // Defines the memory that will actually hold the messages within the message
|
||||||
|
* // buffer.
|
||||||
|
* static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
|
||||||
|
*
|
||||||
|
* // The variable used to hold the message buffer structure.
|
||||||
|
* StaticMessageBuffer_t xMessageBufferStruct;
|
||||||
|
*
|
||||||
|
* void MyFunction( void )
|
||||||
|
* {
|
||||||
|
* MessageBufferHandle_t xMessageBuffer;
|
||||||
|
*
|
||||||
|
* xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucStorageBuffer ),
|
||||||
|
* ucStorageBuffer,
|
||||||
|
* &xMessageBufferStruct );
|
||||||
|
*
|
||||||
|
* // As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer
|
||||||
|
* // parameters were NULL, xMessageBuffer will not be NULL, and can be used to
|
||||||
|
* // reference the created message buffer in other message buffer API calls.
|
||||||
|
*
|
||||||
|
* // Other code that uses the message buffer can go here.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xMessageBufferCreateStatic xMessageBufferCreateStatic
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) \
|
||||||
|
xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), 0, sbTYPE_MESSAGE_BUFFER, ( pucMessageBufferStorageArea ), ( pxStaticMessageBuffer ), NULL, NULL )
|
||||||
|
|
||||||
|
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
|
||||||
|
#define xMessageBufferCreateStaticWithCallback( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
|
||||||
|
xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), 0, sbTYPE_MESSAGE_BUFFER, ( pucMessageBufferStorageArea ), ( pxStaticMessageBuffer ), ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* @code{c}
|
||||||
|
* BaseType_t xMessageBufferGetStaticBuffers( MessageBufferHandle_t xMessageBuffer,
|
||||||
|
* uint8_t ** ppucMessageBufferStorageArea,
|
||||||
|
* StaticMessageBuffer_t ** ppxStaticMessageBuffer );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Retrieve pointers to a statically created message buffer's data structure
|
||||||
|
* buffer and storage area buffer. These are the same buffers that are supplied
|
||||||
|
* at the time of creation.
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferGetStaticBuffers() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The message buffer for which to retrieve the buffers.
|
||||||
|
*
|
||||||
|
* @param ppucMessageBufferStorageArea Used to return a pointer to the
|
||||||
|
* message buffer's storage area buffer.
|
||||||
|
*
|
||||||
|
* @param ppxStaticMessageBuffer Used to return a pointer to the message
|
||||||
|
* buffer's data structure buffer.
|
||||||
|
*
|
||||||
|
* @return pdTRUE if buffers were retrieved, pdFALSE otherwise..
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferGetStaticBuffers xMessageBufferGetStaticBuffers
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
#define xMessageBufferGetStaticBuffers( xMessageBuffer, ppucMessageBufferStorageArea, ppxStaticMessageBuffer ) \
|
||||||
|
xStreamBufferGetStaticBuffers( ( xMessageBuffer ), ( ppucMessageBufferStorageArea ), ( ppxStaticMessageBuffer ) )
|
||||||
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* @code{c}
|
||||||
|
* size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
|
||||||
|
* const void *pvTxData,
|
||||||
|
* size_t xDataLengthBytes,
|
||||||
|
* TickType_t xTicksToWait );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Sends a discrete message to the message buffer. The message can be any
|
||||||
|
* length that fits within the buffer's free space, and is copied into the
|
||||||
|
* buffer.
|
||||||
|
*
|
||||||
|
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||||
|
* implementation (so also the message buffer implementation, as message buffers
|
||||||
|
* are built on top of stream buffers) assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||||
|
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||||
|
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||||
|
* multiple different readers. If there are to be multiple different writers
|
||||||
|
* then the application writer must serialize calls to writing API functions
|
||||||
|
* (such as xStreamBufferSend()). Likewise, if there are to be multiple
|
||||||
|
* different readers then the application writer must serialize calls to reading
|
||||||
|
* API functions (such as xStreamBufferReceive()). One way to achieve such
|
||||||
|
* serialization in single core or SMP kernel is to place each API call inside a
|
||||||
|
* critical section and use a block time of 0.
|
||||||
|
*
|
||||||
|
* Use xMessageBufferSend() to write to a message buffer from a task. Use
|
||||||
|
* xMessageBufferSendFromISR() to write to a message buffer from an interrupt
|
||||||
|
* service routine (ISR).
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferSend() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer to which a message is
|
||||||
|
* being sent.
|
||||||
|
*
|
||||||
|
* @param pvTxData A pointer to the message that is to be copied into the
|
||||||
|
* message buffer.
|
||||||
|
*
|
||||||
|
* @param xDataLengthBytes The length of the message. That is, the number of
|
||||||
|
* bytes to copy from pvTxData into the message buffer. When a message is
|
||||||
|
* written to the message buffer an additional sizeof( size_t ) bytes are also
|
||||||
|
* written to store the message's length. sizeof( size_t ) is typically 4 bytes
|
||||||
|
* on a 32-bit architecture, so on most 32-bit architecture setting
|
||||||
|
* xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
|
||||||
|
* bytes (20 bytes of message data and 4 bytes to hold the message length).
|
||||||
|
*
|
||||||
|
* @param xTicksToWait The maximum amount of time the calling task should remain
|
||||||
|
* in the Blocked state to wait for enough space to become available in the
|
||||||
|
* message buffer, should the message buffer have insufficient space when
|
||||||
|
* xMessageBufferSend() is called. The calling task will never block if
|
||||||
|
* xTicksToWait is zero. The block time is specified in tick periods, so the
|
||||||
|
* absolute time it represents is dependent on the tick frequency. The macro
|
||||||
|
* pdMS_TO_TICKS() can be used to convert a time specified in milliseconds into
|
||||||
|
* a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will cause
|
||||||
|
* the task to wait indefinitely (without timing out), provided
|
||||||
|
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
|
||||||
|
* CPU time when they are in the Blocked state.
|
||||||
|
*
|
||||||
|
* @return The number of bytes written to the message buffer. If the call to
|
||||||
|
* xMessageBufferSend() times out before there was enough space to write the
|
||||||
|
* message into the message buffer then zero is returned. If the call did not
|
||||||
|
* time out then xDataLengthBytes is returned.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* @code{c}
|
||||||
|
* void vAFunction( MessageBufferHandle_t xMessageBuffer )
|
||||||
|
* {
|
||||||
|
* size_t xBytesSent;
|
||||||
|
* uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
|
||||||
|
* char *pcStringToSend = "String to send";
|
||||||
|
* const TickType_t x100ms = pdMS_TO_TICKS( 100 );
|
||||||
|
*
|
||||||
|
* // Send an array to the message buffer, blocking for a maximum of 100ms to
|
||||||
|
* // wait for enough space to be available in the message buffer.
|
||||||
|
* xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
|
||||||
|
*
|
||||||
|
* if( xBytesSent != sizeof( ucArrayToSend ) )
|
||||||
|
* {
|
||||||
|
* // The call to xMessageBufferSend() times out before there was enough
|
||||||
|
* // space in the buffer for the data to be written.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Send the string to the message buffer. Return immediately if there is
|
||||||
|
* // not enough space in the buffer.
|
||||||
|
* xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
|
||||||
|
*
|
||||||
|
* if( xBytesSent != strlen( pcStringToSend ) )
|
||||||
|
* {
|
||||||
|
* // The string could not be added to the message buffer because there was
|
||||||
|
* // not enough free space in the buffer.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xMessageBufferSend xMessageBufferSend
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) \
|
||||||
|
xStreamBufferSend( ( xMessageBuffer ), ( pvTxData ), ( xDataLengthBytes ), ( xTicksToWait ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* @code{c}
|
||||||
|
* size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
|
||||||
|
* const void *pvTxData,
|
||||||
|
* size_t xDataLengthBytes,
|
||||||
|
* BaseType_t *pxHigherPriorityTaskWoken );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Interrupt safe version of the API function that sends a discrete message to
|
||||||
|
* the message buffer. The message can be any length that fits within the
|
||||||
|
* buffer's free space, and is copied into the buffer.
|
||||||
|
*
|
||||||
|
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||||
|
* implementation (so also the message buffer implementation, as message buffers
|
||||||
|
* are built on top of stream buffers) assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||||
|
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||||
|
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||||
|
* multiple different readers. If there are to be multiple different writers
|
||||||
|
* then the application writer must serialize calls to writing API functions
|
||||||
|
* (such as xStreamBufferSend()). Likewise, if there are to be multiple
|
||||||
|
* different readers then the application writer must serialize calls to reading
|
||||||
|
* API functions (such as xStreamBufferReceive()). One way to achieve such
|
||||||
|
* serialization in single core or SMP kernel is to place each API call inside a
|
||||||
|
* critical section and use a block time of 0.
|
||||||
|
*
|
||||||
|
* Use xMessageBufferSend() to write to a message buffer from a task. Use
|
||||||
|
* xMessageBufferSendFromISR() to write to a message buffer from an interrupt
|
||||||
|
* service routine (ISR).
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferSendFromISR() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer to which a message is
|
||||||
|
* being sent.
|
||||||
|
*
|
||||||
|
* @param pvTxData A pointer to the message that is to be copied into the
|
||||||
|
* message buffer.
|
||||||
|
*
|
||||||
|
* @param xDataLengthBytes The length of the message. That is, the number of
|
||||||
|
* bytes to copy from pvTxData into the message buffer. When a message is
|
||||||
|
* written to the message buffer an additional sizeof( size_t ) bytes are also
|
||||||
|
* written to store the message's length. sizeof( size_t ) is typically 4 bytes
|
||||||
|
* on a 32-bit architecture, so on most 32-bit architecture setting
|
||||||
|
* xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
|
||||||
|
* bytes (20 bytes of message data and 4 bytes to hold the message length).
|
||||||
|
*
|
||||||
|
* @param pxHigherPriorityTaskWoken It is possible that a message buffer will
|
||||||
|
* have a task blocked on it waiting for data. Calling
|
||||||
|
* xMessageBufferSendFromISR() can make data available, and so cause a task that
|
||||||
|
* was waiting for data to leave the Blocked state. If calling
|
||||||
|
* xMessageBufferSendFromISR() causes a task to leave the Blocked state, and the
|
||||||
|
* unblocked task has a priority higher than the currently executing task (the
|
||||||
|
* task that was interrupted), then, internally, xMessageBufferSendFromISR()
|
||||||
|
* will set *pxHigherPriorityTaskWoken to pdTRUE. If
|
||||||
|
* xMessageBufferSendFromISR() sets this value to pdTRUE, then normally a
|
||||||
|
* context switch should be performed before the interrupt is exited. This will
|
||||||
|
* ensure that the interrupt returns directly to the highest priority Ready
|
||||||
|
* state task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it
|
||||||
|
* is passed into the function. See the code example below for an example.
|
||||||
|
*
|
||||||
|
* @return The number of bytes actually written to the message buffer. If the
|
||||||
|
* message buffer didn't have enough free space for the message to be stored
|
||||||
|
* then 0 is returned, otherwise xDataLengthBytes is returned.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* @code{c}
|
||||||
|
* // A message buffer that has already been created.
|
||||||
|
* MessageBufferHandle_t xMessageBuffer;
|
||||||
|
*
|
||||||
|
* void vAnInterruptServiceRoutine( void )
|
||||||
|
* {
|
||||||
|
* size_t xBytesSent;
|
||||||
|
* char *pcStringToSend = "String to send";
|
||||||
|
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
|
||||||
|
*
|
||||||
|
* // Attempt to send the string to the message buffer.
|
||||||
|
* xBytesSent = xMessageBufferSendFromISR( xMessageBuffer,
|
||||||
|
* ( void * ) pcStringToSend,
|
||||||
|
* strlen( pcStringToSend ),
|
||||||
|
* &xHigherPriorityTaskWoken );
|
||||||
|
*
|
||||||
|
* if( xBytesSent != strlen( pcStringToSend ) )
|
||||||
|
* {
|
||||||
|
* // The string could not be added to the message buffer because there was
|
||||||
|
* // not enough free space in the buffer.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
|
||||||
|
* // xMessageBufferSendFromISR() then a task that has a priority above the
|
||||||
|
* // priority of the currently executing task was unblocked and a context
|
||||||
|
* // switch should be performed to ensure the ISR returns to the unblocked
|
||||||
|
* // task. In most FreeRTOS ports this is done by simply passing
|
||||||
|
* // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
|
||||||
|
* // variables value, and perform the context switch if necessary. Check the
|
||||||
|
* // documentation for the port in use for port specific instructions.
|
||||||
|
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) \
|
||||||
|
xStreamBufferSendFromISR( ( xMessageBuffer ), ( pvTxData ), ( xDataLengthBytes ), ( pxHigherPriorityTaskWoken ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* @code{c}
|
||||||
|
* size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
|
||||||
|
* void *pvRxData,
|
||||||
|
* size_t xBufferLengthBytes,
|
||||||
|
* TickType_t xTicksToWait );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Receives a discrete message from a message buffer. Messages can be of
|
||||||
|
* variable length and are copied out of the buffer.
|
||||||
|
*
|
||||||
|
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||||
|
* implementation (so also the message buffer implementation, as message buffers
|
||||||
|
* are built on top of stream buffers) assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||||
|
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||||
|
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||||
|
* multiple different readers. If there are to be multiple different writers
|
||||||
|
* then the application writer must serialize calls to writing API functions
|
||||||
|
* (such as xStreamBufferSend()). Likewise, if there are to be multiple
|
||||||
|
* different readers then the application writer must serialize calls to reading
|
||||||
|
* API functions (such as xStreamBufferReceive()). One way to achieve such
|
||||||
|
* serialization in single core or SMP kernel is to place each API call inside a
|
||||||
|
* critical section and use a block time of 0.
|
||||||
|
*
|
||||||
|
* Use xMessageBufferReceive() to read from a message buffer from a task. Use
|
||||||
|
* xMessageBufferReceiveFromISR() to read from a message buffer from an
|
||||||
|
* interrupt service routine (ISR).
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferReceive() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer from which a message
|
||||||
|
* is being received.
|
||||||
|
*
|
||||||
|
* @param pvRxData A pointer to the buffer into which the received message is
|
||||||
|
* to be copied.
|
||||||
|
*
|
||||||
|
* @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
|
||||||
|
* parameter. This sets the maximum length of the message that can be received.
|
||||||
|
* If xBufferLengthBytes is too small to hold the next message then the message
|
||||||
|
* will be left in the message buffer and 0 will be returned.
|
||||||
|
*
|
||||||
|
* @param xTicksToWait The maximum amount of time the task should remain in the
|
||||||
|
* Blocked state to wait for a message, should the message buffer be empty.
|
||||||
|
* xMessageBufferReceive() will return immediately if xTicksToWait is zero and
|
||||||
|
* the message buffer is empty. The block time is specified in tick periods, so
|
||||||
|
* the absolute time it represents is dependent on the tick frequency. The
|
||||||
|
* macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
|
||||||
|
* into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will
|
||||||
|
* cause the task to wait indefinitely (without timing out), provided
|
||||||
|
* INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
|
||||||
|
* CPU time when they are in the Blocked state.
|
||||||
|
*
|
||||||
|
* @return The length, in bytes, of the message read from the message buffer, if
|
||||||
|
* any. If xMessageBufferReceive() times out before a message became available
|
||||||
|
* then zero is returned. If the length of the message is greater than
|
||||||
|
* xBufferLengthBytes then the message will be left in the message buffer and
|
||||||
|
* zero is returned.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* @code{c}
|
||||||
|
* void vAFunction( MessageBuffer_t xMessageBuffer )
|
||||||
|
* {
|
||||||
|
* uint8_t ucRxData[ 20 ];
|
||||||
|
* size_t xReceivedBytes;
|
||||||
|
* const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
|
||||||
|
*
|
||||||
|
* // Receive the next message from the message buffer. Wait in the Blocked
|
||||||
|
* // state (so not using any CPU processing time) for a maximum of 100ms for
|
||||||
|
* // a message to become available.
|
||||||
|
* xReceivedBytes = xMessageBufferReceive( xMessageBuffer,
|
||||||
|
* ( void * ) ucRxData,
|
||||||
|
* sizeof( ucRxData ),
|
||||||
|
* xBlockTime );
|
||||||
|
*
|
||||||
|
* if( xReceivedBytes > 0 )
|
||||||
|
* {
|
||||||
|
* // A ucRxData contains a message that is xReceivedBytes long. Process
|
||||||
|
* // the message here....
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xMessageBufferReceive xMessageBufferReceive
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) \
|
||||||
|
xStreamBufferReceive( ( xMessageBuffer ), ( pvRxData ), ( xBufferLengthBytes ), ( xTicksToWait ) )
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* @code{c}
|
||||||
|
* size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
|
||||||
|
* void *pvRxData,
|
||||||
|
* size_t xBufferLengthBytes,
|
||||||
|
* BaseType_t *pxHigherPriorityTaskWoken );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* An interrupt safe version of the API function that receives a discrete
|
||||||
|
* message from a message buffer. Messages can be of variable length and are
|
||||||
|
* copied out of the buffer.
|
||||||
|
*
|
||||||
|
* ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
|
||||||
|
* implementation (so also the message buffer implementation, as message buffers
|
||||||
|
* are built on top of stream buffers) assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader). It is safe for the
|
||||||
|
* writer and reader to be different tasks or interrupts, but, unlike other
|
||||||
|
* FreeRTOS objects, it is not safe to have multiple different writers or
|
||||||
|
* multiple different readers. If there are to be multiple different writers
|
||||||
|
* then the application writer must serialize calls to writing API functions
|
||||||
|
* (such as xStreamBufferSend()). Likewise, if there are to be multiple
|
||||||
|
* different readers then the application writer must serialize calls to reading
|
||||||
|
* API functions (such as xStreamBufferReceive()). One way to achieve such
|
||||||
|
* serialization in single core or SMP kernel is to place each API call inside a
|
||||||
|
* critical section and use a block time of 0.
|
||||||
|
*
|
||||||
|
* Use xMessageBufferReceive() to read from a message buffer from a task. Use
|
||||||
|
* xMessageBufferReceiveFromISR() to read from a message buffer from an
|
||||||
|
* interrupt service routine (ISR).
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferReceiveFromISR() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer from which a message
|
||||||
|
* is being received.
|
||||||
|
*
|
||||||
|
* @param pvRxData A pointer to the buffer into which the received message is
|
||||||
|
* to be copied.
|
||||||
|
*
|
||||||
|
* @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
|
||||||
|
* parameter. This sets the maximum length of the message that can be received.
|
||||||
|
* If xBufferLengthBytes is too small to hold the next message then the message
|
||||||
|
* will be left in the message buffer and 0 will be returned.
|
||||||
|
*
|
||||||
|
* @param pxHigherPriorityTaskWoken It is possible that a message buffer will
|
||||||
|
* have a task blocked on it waiting for space to become available. Calling
|
||||||
|
* xMessageBufferReceiveFromISR() can make space available, and so cause a task
|
||||||
|
* that is waiting for space to leave the Blocked state. If calling
|
||||||
|
* xMessageBufferReceiveFromISR() causes a task to leave the Blocked state, and
|
||||||
|
* the unblocked task has a priority higher than the currently executing task
|
||||||
|
* (the task that was interrupted), then, internally,
|
||||||
|
* xMessageBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE.
|
||||||
|
* If xMessageBufferReceiveFromISR() sets this value to pdTRUE, then normally a
|
||||||
|
* context switch should be performed before the interrupt is exited. That will
|
||||||
|
* ensure the interrupt returns directly to the highest priority Ready state
|
||||||
|
* task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it is
|
||||||
|
* passed into the function. See the code example below for an example.
|
||||||
|
*
|
||||||
|
* @return The length, in bytes, of the message read from the message buffer, if
|
||||||
|
* any.
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* @code{c}
|
||||||
|
* // A message buffer that has already been created.
|
||||||
|
* MessageBuffer_t xMessageBuffer;
|
||||||
|
*
|
||||||
|
* void vAnInterruptServiceRoutine( void )
|
||||||
|
* {
|
||||||
|
* uint8_t ucRxData[ 20 ];
|
||||||
|
* size_t xReceivedBytes;
|
||||||
|
* BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
|
||||||
|
*
|
||||||
|
* // Receive the next message from the message buffer.
|
||||||
|
* xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer,
|
||||||
|
* ( void * ) ucRxData,
|
||||||
|
* sizeof( ucRxData ),
|
||||||
|
* &xHigherPriorityTaskWoken );
|
||||||
|
*
|
||||||
|
* if( xReceivedBytes > 0 )
|
||||||
|
* {
|
||||||
|
* // A ucRxData contains a message that is xReceivedBytes long. Process
|
||||||
|
* // the message here....
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // If xHigherPriorityTaskWoken was set to pdTRUE inside
|
||||||
|
* // xMessageBufferReceiveFromISR() then a task that has a priority above the
|
||||||
|
* // priority of the currently executing task was unblocked and a context
|
||||||
|
* // switch should be performed to ensure the ISR returns to the unblocked
|
||||||
|
* // task. In most FreeRTOS ports this is done by simply passing
|
||||||
|
* // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
|
||||||
|
* // variables value, and perform the context switch if necessary. Check the
|
||||||
|
* // documentation for the port in use for port specific instructions.
|
||||||
|
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) \
|
||||||
|
xStreamBufferReceiveFromISR( ( xMessageBuffer ), ( pvRxData ), ( xBufferLengthBytes ), ( pxHigherPriorityTaskWoken ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* @code{c}
|
||||||
|
* void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Deletes a message buffer that was previously created using a call to
|
||||||
|
* xMessageBufferCreate() or xMessageBufferCreateStatic(). If the message
|
||||||
|
* buffer was created using dynamic memory (that is, by xMessageBufferCreate()),
|
||||||
|
* then the allocated memory is freed.
|
||||||
|
*
|
||||||
|
* A message buffer handle must not be used after the message buffer has been
|
||||||
|
* deleted.
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* vMessageBufferDelete() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer to be deleted.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define vMessageBufferDelete( xMessageBuffer ) \
|
||||||
|
vStreamBufferDelete( xMessageBuffer )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
* @code{c}
|
||||||
|
* BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Tests to see if a message buffer is full. A message buffer is full if it
|
||||||
|
* cannot accept any more messages, of any size, until space is made available
|
||||||
|
* by a message being removed from the message buffer.
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferIsFull() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||||
|
*
|
||||||
|
* @return If the message buffer referenced by xMessageBuffer is full then
|
||||||
|
* pdTRUE is returned. Otherwise pdFALSE is returned.
|
||||||
|
*/
|
||||||
|
#define xMessageBufferIsFull( xMessageBuffer ) \
|
||||||
|
xStreamBufferIsFull( xMessageBuffer )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
* @code{c}
|
||||||
|
* BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Tests to see if a message buffer is empty (does not contain any messages).
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferIsEmpty() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||||
|
*
|
||||||
|
* @return If the message buffer referenced by xMessageBuffer is empty then
|
||||||
|
* pdTRUE is returned. Otherwise pdFALSE is returned.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define xMessageBufferIsEmpty( xMessageBuffer ) \
|
||||||
|
xStreamBufferIsEmpty( xMessageBuffer )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
* @code{c}
|
||||||
|
* BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Resets a message buffer to its initial empty state, discarding any message it
|
||||||
|
* contained.
|
||||||
|
*
|
||||||
|
* A message buffer can only be reset if there are no tasks blocked on it.
|
||||||
|
*
|
||||||
|
* Use xMessageBufferReset() to reset a message buffer from a task.
|
||||||
|
* Use xMessageBufferResetFromISR() to reset a message buffer from an
|
||||||
|
* interrupt service routine (ISR).
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferReset() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer being reset.
|
||||||
|
*
|
||||||
|
* @return If the message buffer was reset then pdPASS is returned. If the
|
||||||
|
* message buffer could not be reset because either there was a task blocked on
|
||||||
|
* the message queue to wait for space to become available, or to wait for a
|
||||||
|
* a message to be available, then pdFAIL is returned.
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferReset xMessageBufferReset
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferReset( xMessageBuffer ) \
|
||||||
|
xStreamBufferReset( xMessageBuffer )
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
* @code{c}
|
||||||
|
* BaseType_t xMessageBufferResetFromISR( MessageBufferHandle_t xMessageBuffer );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* An interrupt safe version of the API function that resets the message buffer.
|
||||||
|
* Resets a message buffer to its initial empty state, discarding any message it
|
||||||
|
* contained.
|
||||||
|
*
|
||||||
|
* A message buffer can only be reset if there are no tasks blocked on it.
|
||||||
|
*
|
||||||
|
* Use xMessageBufferReset() to reset a message buffer from a task.
|
||||||
|
* Use xMessageBufferResetFromISR() to reset a message buffer from an
|
||||||
|
* interrupt service routine (ISR).
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferResetFromISR() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer being reset.
|
||||||
|
*
|
||||||
|
* @return If the message buffer was reset then pdPASS is returned. If the
|
||||||
|
* message buffer could not be reset because either there was a task blocked on
|
||||||
|
* the message queue to wait for space to become available, or to wait for a
|
||||||
|
* a message to be available, then pdFAIL is returned.
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferResetFromISR xMessageBufferResetFromISR
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferResetFromISR( xMessageBuffer ) \
|
||||||
|
xStreamBufferResetFromISR( xMessageBuffer )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
* @code{c}
|
||||||
|
* size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer );
|
||||||
|
* @endcode
|
||||||
|
* Returns the number of bytes of free space in the message buffer.
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferSpaceAvailable() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||||
|
*
|
||||||
|
* @return The number of bytes that can be written to the message buffer before
|
||||||
|
* the message buffer would be full. When a message is written to the message
|
||||||
|
* buffer an additional sizeof( size_t ) bytes are also written to store the
|
||||||
|
* message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
|
||||||
|
* architecture, so if xMessageBufferSpacesAvailable() returns 10, then the size
|
||||||
|
* of the largest message that can be written to the message buffer is 6 bytes.
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferSpaceAvailable xMessageBufferSpaceAvailable
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferSpaceAvailable( xMessageBuffer ) \
|
||||||
|
xStreamBufferSpacesAvailable( xMessageBuffer )
|
||||||
|
#define xMessageBufferSpacesAvailable( xMessageBuffer ) \
|
||||||
|
xStreamBufferSpacesAvailable( xMessageBuffer ) /* Corrects typo in original macro name. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
* @code{c}
|
||||||
|
* size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer );
|
||||||
|
* @endcode
|
||||||
|
* Returns the length (in bytes) of the next message in a message buffer.
|
||||||
|
* Useful if xMessageBufferReceive() returned 0 because the size of the buffer
|
||||||
|
* passed into xMessageBufferReceive() was too small to hold the next message.
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferNextLengthBytes() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the message buffer being queried.
|
||||||
|
*
|
||||||
|
* @return The length (in bytes) of the next message in the message buffer, or 0
|
||||||
|
* if the message buffer is empty.
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferNextLengthBytes xMessageBufferNextLengthBytes
|
||||||
|
* \ingroup MessageBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferNextLengthBytes( xMessageBuffer ) \
|
||||||
|
xStreamBufferNextMessageLengthBytes( xMessageBuffer )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* @code{c}
|
||||||
|
* BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xMessageBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* For advanced users only.
|
||||||
|
*
|
||||||
|
* The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when
|
||||||
|
* data is sent to a message buffer or stream buffer. If there was a task that
|
||||||
|
* was blocked on the message or stream buffer waiting for data to arrive then
|
||||||
|
* the sbSEND_COMPLETED() macro sends a notification to the task to remove it
|
||||||
|
* from the Blocked state. xMessageBufferSendCompletedFromISR() does the same
|
||||||
|
* thing. It is provided to enable application writers to implement their own
|
||||||
|
* version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME.
|
||||||
|
*
|
||||||
|
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
|
||||||
|
* additional information.
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferSendCompletedFromISR() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the stream buffer to which data was
|
||||||
|
* written.
|
||||||
|
*
|
||||||
|
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
|
||||||
|
* initialised to pdFALSE before it is passed into
|
||||||
|
* xMessageBufferSendCompletedFromISR(). If calling
|
||||||
|
* xMessageBufferSendCompletedFromISR() removes a task from the Blocked state,
|
||||||
|
* and the task has a priority above the priority of the currently running task,
|
||||||
|
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
|
||||||
|
* context switch should be performed before exiting the ISR.
|
||||||
|
*
|
||||||
|
* @return If a task was removed from the Blocked state then pdTRUE is returned.
|
||||||
|
* Otherwise pdFALSE is returned.
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferSendCompletedFromISR xMessageBufferSendCompletedFromISR
|
||||||
|
* \ingroup StreamBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
|
||||||
|
xStreamBufferSendCompletedFromISR( ( xMessageBuffer ), ( pxHigherPriorityTaskWoken ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* message_buffer.h
|
||||||
|
*
|
||||||
|
* @code{c}
|
||||||
|
* BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xMessageBuffer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* For advanced users only.
|
||||||
|
*
|
||||||
|
* The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when
|
||||||
|
* data is read out of a message buffer or stream buffer. If there was a task
|
||||||
|
* that was blocked on the message or stream buffer waiting for data to arrive
|
||||||
|
* then the sbRECEIVE_COMPLETED() macro sends a notification to the task to
|
||||||
|
* remove it from the Blocked state. xMessageBufferReceiveCompletedFromISR()
|
||||||
|
* does the same thing. It is provided to enable application writers to
|
||||||
|
* implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT
|
||||||
|
* ANY OTHER TIME.
|
||||||
|
*
|
||||||
|
* See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
|
||||||
|
* additional information.
|
||||||
|
*
|
||||||
|
* configUSE_STREAM_BUFFERS must be set to 1 in for FreeRTOSConfig.h for
|
||||||
|
* xMessageBufferReceiveCompletedFromISR() to be available.
|
||||||
|
*
|
||||||
|
* @param xMessageBuffer The handle of the stream buffer from which data was
|
||||||
|
* read.
|
||||||
|
*
|
||||||
|
* @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
|
||||||
|
* initialised to pdFALSE before it is passed into
|
||||||
|
* xMessageBufferReceiveCompletedFromISR(). If calling
|
||||||
|
* xMessageBufferReceiveCompletedFromISR() removes a task from the Blocked state,
|
||||||
|
* and the task has a priority above the priority of the currently running task,
|
||||||
|
* then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
|
||||||
|
* context switch should be performed before exiting the ISR.
|
||||||
|
*
|
||||||
|
* @return If a task was removed from the Blocked state then pdTRUE is returned.
|
||||||
|
* Otherwise pdFALSE is returned.
|
||||||
|
*
|
||||||
|
* \defgroup xMessageBufferReceiveCompletedFromISR xMessageBufferReceiveCompletedFromISR
|
||||||
|
* \ingroup StreamBufferManagement
|
||||||
|
*/
|
||||||
|
#define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
|
||||||
|
xStreamBufferReceiveCompletedFromISR( ( xMessageBuffer ), ( pxHigherPriorityTaskWoken ) )
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#if defined( __cplusplus )
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */
|
||||||
@@ -0,0 +1,495 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the MPU is used the standard (non MPU) API functions are mapped to
|
||||||
|
* equivalents that start "MPU_", the prototypes for which are defined in this
|
||||||
|
* header files. This will cause the application code to call the MPU_ version
|
||||||
|
* which wraps the non-MPU version with privilege promoting then demoting code,
|
||||||
|
* so the kernel code always runs will full privileges.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MPU_PROTOTYPES_H
|
||||||
|
#define MPU_PROTOTYPES_H
|
||||||
|
|
||||||
|
typedef struct xTaskGenericNotifyParams
|
||||||
|
{
|
||||||
|
TaskHandle_t xTaskToNotify;
|
||||||
|
UBaseType_t uxIndexToNotify;
|
||||||
|
uint32_t ulValue;
|
||||||
|
eNotifyAction eAction;
|
||||||
|
uint32_t * pulPreviousNotificationValue;
|
||||||
|
} xTaskGenericNotifyParams_t;
|
||||||
|
|
||||||
|
typedef struct xTaskGenericNotifyWaitParams
|
||||||
|
{
|
||||||
|
UBaseType_t uxIndexToWaitOn;
|
||||||
|
uint32_t ulBitsToClearOnEntry;
|
||||||
|
uint32_t ulBitsToClearOnExit;
|
||||||
|
uint32_t * pulNotificationValue;
|
||||||
|
TickType_t xTicksToWait;
|
||||||
|
} xTaskGenericNotifyWaitParams_t;
|
||||||
|
|
||||||
|
typedef struct xTimerGenericCommandFromTaskParams
|
||||||
|
{
|
||||||
|
TimerHandle_t xTimer;
|
||||||
|
BaseType_t xCommandID;
|
||||||
|
TickType_t xOptionalValue;
|
||||||
|
BaseType_t * pxHigherPriorityTaskWoken;
|
||||||
|
TickType_t xTicksToWait;
|
||||||
|
} xTimerGenericCommandFromTaskParams_t;
|
||||||
|
|
||||||
|
typedef struct xEventGroupWaitBitsParams
|
||||||
|
{
|
||||||
|
EventGroupHandle_t xEventGroup;
|
||||||
|
EventBits_t uxBitsToWaitFor;
|
||||||
|
BaseType_t xClearOnExit;
|
||||||
|
BaseType_t xWaitForAllBits;
|
||||||
|
TickType_t xTicksToWait;
|
||||||
|
} xEventGroupWaitBitsParams_t;
|
||||||
|
|
||||||
|
/* MPU versions of task.h API functions. */
|
||||||
|
void MPU_vTaskDelay( const TickType_t xTicksToDelay ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
|
||||||
|
const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
eTaskState MPU_eTaskGetState( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskGetInfo( TaskHandle_t xTask,
|
||||||
|
TaskStatus_t * pxTaskStatus,
|
||||||
|
BaseType_t xGetFreeStackSpace,
|
||||||
|
eTaskState eState ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskResume( TaskHandle_t xTaskToResume ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TickType_t MPU_xTaskGetTickCount( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask,
|
||||||
|
TaskHookFunction_t pxHookFunction ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
|
||||||
|
BaseType_t xIndex,
|
||||||
|
void * pvValue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
|
||||||
|
BaseType_t xIndex ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
|
||||||
|
const UBaseType_t uxArraySize,
|
||||||
|
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL;
|
||||||
|
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetRunTimePercent( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimePercent( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify,
|
||||||
|
UBaseType_t uxIndexToNotify,
|
||||||
|
uint32_t ulValue,
|
||||||
|
eNotifyAction eAction,
|
||||||
|
uint32_t * pulPreviousNotificationValue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskGenericNotifyEntry( const xTaskGenericNotifyParams_t * pxParams ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
|
||||||
|
uint32_t ulBitsToClearOnEntry,
|
||||||
|
uint32_t ulBitsToClearOnExit,
|
||||||
|
uint32_t * pulNotificationValue,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskGenericNotifyWaitEntry( const xTaskGenericNotifyWaitParams_t * pxParams ) FREERTOS_SYSTEM_CALL;
|
||||||
|
uint32_t MPU_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
|
||||||
|
BaseType_t xClearCountOnExit,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskGenericNotifyStateClear( TaskHandle_t xTask,
|
||||||
|
UBaseType_t uxIndexToClear ) FREERTOS_SYSTEM_CALL;
|
||||||
|
uint32_t MPU_ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
|
||||||
|
UBaseType_t uxIndexToClear,
|
||||||
|
uint32_t ulBitsToClear ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
|
||||||
|
TickType_t * const pxTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
/* Privileged only wrappers for Task APIs. These are needed so that
|
||||||
|
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||||
|
* with all the APIs. */
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 1 )
|
||||||
|
|
||||||
|
BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode,
|
||||||
|
const char * const pcName,
|
||||||
|
const configSTACK_DEPTH_TYPE uxStackDepth,
|
||||||
|
void * const pvParameters,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
TaskHandle_t * const pxCreatedTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode,
|
||||||
|
const char * const pcName,
|
||||||
|
const configSTACK_DEPTH_TYPE uxStackDepth,
|
||||||
|
void * const pvParameters,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
StackType_t * const puxStackBuffer,
|
||||||
|
StaticTask_t * const pxTaskBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskPrioritySet( TaskHandle_t xTask,
|
||||||
|
UBaseType_t uxNewPriority ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask,
|
||||||
|
void * pvParameter ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskGetRunTimeStatistics( char * pcWriteBuffer,
|
||||||
|
size_t uxBufferLength ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskListTasks( char * pcWriteBuffer,
|
||||||
|
size_t uxBufferLength ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTaskSuspendAll( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTaskResumeAll( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
#else /* #if ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
|
||||||
|
|
||||||
|
BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode,
|
||||||
|
const char * const pcName,
|
||||||
|
const configSTACK_DEPTH_TYPE uxStackDepth,
|
||||||
|
void * const pvParameters,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
|
||||||
|
TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode,
|
||||||
|
const char * const pcName,
|
||||||
|
const configSTACK_DEPTH_TYPE uxStackDepth,
|
||||||
|
void * const pvParameters,
|
||||||
|
UBaseType_t uxPriority,
|
||||||
|
StackType_t * const puxStackBuffer,
|
||||||
|
StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;
|
||||||
|
void MPU_vTaskPrioritySet( TaskHandle_t xTask,
|
||||||
|
UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION;
|
||||||
|
TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask,
|
||||||
|
void * pvParameter ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
|
||||||
|
|
||||||
|
char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
|
||||||
|
TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition,
|
||||||
|
TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION;
|
||||||
|
void MPU_vTaskAllocateMPURegions( TaskHandle_t xTaskToModify,
|
||||||
|
const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xTaskGetStaticBuffers( TaskHandle_t xTask,
|
||||||
|
StackType_t ** ppuxStackBuffer,
|
||||||
|
StaticTask_t ** ppxTaskBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
UBaseType_t MPU_uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
||||||
|
UBaseType_t MPU_uxTaskBasePriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
||||||
|
UBaseType_t MPU_uxTaskBasePriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
|
||||||
|
TaskHookFunction_t MPU_xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
|
||||||
|
UBaseType_t uxIndexToNotify,
|
||||||
|
uint32_t ulValue,
|
||||||
|
eNotifyAction eAction,
|
||||||
|
uint32_t * pulPreviousNotificationValue,
|
||||||
|
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
void MPU_vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
|
||||||
|
UBaseType_t uxIndexToNotify,
|
||||||
|
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/* MPU versions of queue.h API functions. */
|
||||||
|
BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue,
|
||||||
|
const void * const pvItemToQueue,
|
||||||
|
TickType_t xTicksToWait,
|
||||||
|
const BaseType_t xCopyPosition ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue,
|
||||||
|
void * const pvBuffer,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue,
|
||||||
|
void * const pvBuffer,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vQueueAddToRegistry( QueueHandle_t xQueue,
|
||||||
|
const char * pcName ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
|
||||||
|
QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
|
||||||
|
const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue,
|
||||||
|
UBaseType_t uxQueueNumber ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
/* Privileged only wrappers for Queue APIs. These are needed so that
|
||||||
|
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||||
|
* with all the APIs. */
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 1 )
|
||||||
|
|
||||||
|
void MPU_vQueueDelete( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType,
|
||||||
|
StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
|
||||||
|
const UBaseType_t uxInitialCount ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
|
||||||
|
const UBaseType_t uxInitialCount,
|
||||||
|
StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength,
|
||||||
|
const UBaseType_t uxItemSize,
|
||||||
|
const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength,
|
||||||
|
const UBaseType_t uxItemSize,
|
||||||
|
uint8_t * pucQueueStorage,
|
||||||
|
StaticQueue_t * pxStaticQueue,
|
||||||
|
const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) FREERTOS_SYSTEM_CALL;
|
||||||
|
QueueSetHandle_t MPU_xQueueCreateSetStatic( const UBaseType_t uxEventQueueLength,
|
||||||
|
uint8_t * pucQueueStorage,
|
||||||
|
StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
|
||||||
|
QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue,
|
||||||
|
BaseType_t xNewQueue ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
#else /* #if ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
|
||||||
|
|
||||||
|
void MPU_vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||||
|
QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
|
||||||
|
QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType,
|
||||||
|
StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION;
|
||||||
|
QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
|
||||||
|
const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION;
|
||||||
|
QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
|
||||||
|
const UBaseType_t uxInitialCount,
|
||||||
|
StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION;
|
||||||
|
QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength,
|
||||||
|
const UBaseType_t uxItemSize,
|
||||||
|
const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
|
||||||
|
QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength,
|
||||||
|
const UBaseType_t uxItemSize,
|
||||||
|
uint8_t * pucQueueStorage,
|
||||||
|
StaticQueue_t * pxStaticQueue,
|
||||||
|
const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
|
||||||
|
QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION;
|
||||||
|
QueueSetHandle_t MPU_xQueueCreateSetStatic( const UBaseType_t uxEventQueueLength,
|
||||||
|
uint8_t * pucQueueStorage,
|
||||||
|
StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
|
||||||
|
QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue,
|
||||||
|
BaseType_t xNewQueue ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
|
||||||
|
|
||||||
|
BaseType_t MPU_xQueueGenericGetStaticBuffers( QueueHandle_t xQueue,
|
||||||
|
uint8_t ** ppucQueueStorage,
|
||||||
|
StaticQueue_t ** ppxStaticQueue ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xQueueGenericSendFromISR( QueueHandle_t xQueue,
|
||||||
|
const void * const pvItemToQueue,
|
||||||
|
BaseType_t * const pxHigherPriorityTaskWoken,
|
||||||
|
const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xQueueGiveFromISR( QueueHandle_t xQueue,
|
||||||
|
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xQueuePeekFromISR( QueueHandle_t xQueue,
|
||||||
|
void * const pvBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xQueueReceiveFromISR( QueueHandle_t xQueue,
|
||||||
|
void * const pvBuffer,
|
||||||
|
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||||
|
UBaseType_t MPU_uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||||
|
TaskHandle_t MPU_xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
|
||||||
|
QueueSetMemberHandle_t MPU_xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/* MPU versions of timers.h API functions. */
|
||||||
|
void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTimerSetTimerID( TimerHandle_t xTimer,
|
||||||
|
void * pvNewID ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTimerGenericCommandFromTask( TimerHandle_t xTimer,
|
||||||
|
const BaseType_t xCommandID,
|
||||||
|
const TickType_t xOptionalValue,
|
||||||
|
BaseType_t * const pxHigherPriorityTaskWoken,
|
||||||
|
const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTimerGenericCommandFromTaskEntry( const xTimerGenericCommandFromTaskParams_t * pxParams ) FREERTOS_SYSTEM_CALL;
|
||||||
|
const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vTimerSetReloadMode( TimerHandle_t xTimer,
|
||||||
|
const BaseType_t xAutoReload ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
/* Privileged only wrappers for Timer APIs. These are needed so that
|
||||||
|
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||||
|
* with all the APIs. */
|
||||||
|
TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName,
|
||||||
|
const TickType_t xTimerPeriodInTicks,
|
||||||
|
const BaseType_t xAutoReload,
|
||||||
|
void * const pvTimerID,
|
||||||
|
TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION;
|
||||||
|
TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName,
|
||||||
|
const TickType_t xTimerPeriodInTicks,
|
||||||
|
const BaseType_t xAutoReload,
|
||||||
|
void * const pvTimerID,
|
||||||
|
TimerCallbackFunction_t pxCallbackFunction,
|
||||||
|
StaticTimer_t * pxTimerBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xTimerGetStaticBuffer( TimerHandle_t xTimer,
|
||||||
|
StaticTimer_t ** ppxTimerBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xTimerGenericCommandFromISR( TimerHandle_t xTimer,
|
||||||
|
const BaseType_t xCommandID,
|
||||||
|
const TickType_t xOptionalValue,
|
||||||
|
BaseType_t * const pxHigherPriorityTaskWoken,
|
||||||
|
const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/* MPU versions of event_group.h API functions. */
|
||||||
|
EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
const BaseType_t xClearOnExit,
|
||||||
|
const BaseType_t xWaitForAllBits,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
EventBits_t MPU_xEventGroupWaitBitsEntry( const xEventGroupWaitBitsParams_t * pxParams ) FREERTOS_SYSTEM_CALL;
|
||||||
|
EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL;
|
||||||
|
EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet ) FREERTOS_SYSTEM_CALL;
|
||||||
|
EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet,
|
||||||
|
const EventBits_t uxBitsToWaitFor,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vEventGroupSetNumber( void * xEventGroup,
|
||||||
|
UBaseType_t uxEventGroupNumber ) FREERTOS_SYSTEM_CALL;
|
||||||
|
#endif /* #if ( configUSE_TRACE_FACILITY == 1 ) */
|
||||||
|
|
||||||
|
/* Privileged only wrappers for Event Group APIs. These are needed so that
|
||||||
|
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||||
|
* with all the APIs. */
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 1 )
|
||||||
|
|
||||||
|
EventGroupHandle_t MPU_xEventGroupCreate( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
#else /* #if ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
|
||||||
|
|
||||||
|
EventGroupHandle_t MPU_xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
|
||||||
|
EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
|
||||||
|
|
||||||
|
BaseType_t MPU_xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
|
||||||
|
StaticEventGroup_t ** ppxEventGroupBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
EventBits_t MPU_xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||||
|
BaseType_t MPU_xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
|
||||||
|
const EventBits_t uxBitsToSet,
|
||||||
|
BaseType_t * pxHigherPriorityTaskWoken ) FREERTOS_SYSTEM_CALL;
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
/* MPU versions of message/stream_buffer.h API functions. */
|
||||||
|
size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
|
||||||
|
const void * pvTxData,
|
||||||
|
size_t xDataLengthBytes,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
|
||||||
|
void * pvRxData,
|
||||||
|
size_t xBufferLengthBytes,
|
||||||
|
TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
|
||||||
|
size_t xTriggerLevel ) FREERTOS_SYSTEM_CALL;
|
||||||
|
size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
/* Privileged only wrappers for Stream Buffer APIs. These are needed so that
|
||||||
|
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||||
|
* with all the APIs. */
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 1 )
|
||||||
|
|
||||||
|
StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes,
|
||||||
|
size_t xTriggerLevelBytes,
|
||||||
|
BaseType_t xStreamBufferType,
|
||||||
|
StreamBufferCallbackFunction_t pxSendCompletedCallback,
|
||||||
|
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) FREERTOS_SYSTEM_CALL;
|
||||||
|
StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
|
||||||
|
size_t xTriggerLevelBytes,
|
||||||
|
BaseType_t xStreamBufferType,
|
||||||
|
uint8_t * const pucStreamBufferStorageArea,
|
||||||
|
StaticStreamBuffer_t * const pxStaticStreamBuffer,
|
||||||
|
StreamBufferCallbackFunction_t pxSendCompletedCallback,
|
||||||
|
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) FREERTOS_SYSTEM_CALL;
|
||||||
|
void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
||||||
|
#else /* #if ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
|
||||||
|
|
||||||
|
StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes,
|
||||||
|
size_t xTriggerLevelBytes,
|
||||||
|
BaseType_t xStreamBufferType,
|
||||||
|
StreamBufferCallbackFunction_t pxSendCompletedCallback,
|
||||||
|
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
|
||||||
|
StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
|
||||||
|
size_t xTriggerLevelBytes,
|
||||||
|
BaseType_t xStreamBufferType,
|
||||||
|
uint8_t * const pucStreamBufferStorageArea,
|
||||||
|
StaticStreamBuffer_t * const pxStaticStreamBuffer,
|
||||||
|
StreamBufferCallbackFunction_t pxSendCompletedCallback,
|
||||||
|
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
|
||||||
|
void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
|
||||||
|
|
||||||
|
BaseType_t MPU_xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffers,
|
||||||
|
uint8_t * ppucStreamBufferStorageArea,
|
||||||
|
StaticStreamBuffer_t * ppxStaticStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
size_t MPU_xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||||
|
const void * pvTxData,
|
||||||
|
size_t xDataLengthBytes,
|
||||||
|
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
size_t MPU_xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||||
|
void * pvRxData,
|
||||||
|
size_t xBufferLengthBytes,
|
||||||
|
BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||||
|
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||||
|
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t MPU_xStreamBufferResetFromISR( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
#endif /* MPU_PROTOTYPES_H */
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MPU_SYSCALL_NUMBERS_H
|
||||||
|
#define MPU_SYSCALL_NUMBERS_H
|
||||||
|
|
||||||
|
/* Numbers assigned to various system calls. */
|
||||||
|
#define SYSTEM_CALL_xTaskGenericNotify 0
|
||||||
|
#define SYSTEM_CALL_xTaskGenericNotifyWait 1
|
||||||
|
#define SYSTEM_CALL_xTimerGenericCommandFromTask 2
|
||||||
|
#define SYSTEM_CALL_xEventGroupWaitBits 3
|
||||||
|
#define SYSTEM_CALL_xTaskDelayUntil 4
|
||||||
|
#define SYSTEM_CALL_xTaskAbortDelay 5
|
||||||
|
#define SYSTEM_CALL_vTaskDelay 6
|
||||||
|
#define SYSTEM_CALL_uxTaskPriorityGet 7
|
||||||
|
#define SYSTEM_CALL_eTaskGetState 8
|
||||||
|
#define SYSTEM_CALL_vTaskGetInfo 9
|
||||||
|
#define SYSTEM_CALL_xTaskGetIdleTaskHandle 10
|
||||||
|
#define SYSTEM_CALL_vTaskSuspend 11
|
||||||
|
#define SYSTEM_CALL_vTaskResume 12
|
||||||
|
#define SYSTEM_CALL_xTaskGetTickCount 13
|
||||||
|
#define SYSTEM_CALL_uxTaskGetNumberOfTasks 14
|
||||||
|
#define SYSTEM_CALL_ulTaskGetRunTimeCounter 15
|
||||||
|
#define SYSTEM_CALL_ulTaskGetRunTimePercent 16
|
||||||
|
#define SYSTEM_CALL_ulTaskGetIdleRunTimePercent 17
|
||||||
|
#define SYSTEM_CALL_ulTaskGetIdleRunTimeCounter 18
|
||||||
|
#define SYSTEM_CALL_vTaskSetApplicationTaskTag 19
|
||||||
|
#define SYSTEM_CALL_xTaskGetApplicationTaskTag 20
|
||||||
|
#define SYSTEM_CALL_vTaskSetThreadLocalStoragePointer 21
|
||||||
|
#define SYSTEM_CALL_pvTaskGetThreadLocalStoragePointer 22
|
||||||
|
#define SYSTEM_CALL_uxTaskGetSystemState 23
|
||||||
|
#define SYSTEM_CALL_uxTaskGetStackHighWaterMark 24
|
||||||
|
#define SYSTEM_CALL_uxTaskGetStackHighWaterMark2 25
|
||||||
|
#define SYSTEM_CALL_xTaskGetCurrentTaskHandle 26
|
||||||
|
#define SYSTEM_CALL_xTaskGetSchedulerState 27
|
||||||
|
#define SYSTEM_CALL_vTaskSetTimeOutState 28
|
||||||
|
#define SYSTEM_CALL_xTaskCheckForTimeOut 29
|
||||||
|
#define SYSTEM_CALL_ulTaskGenericNotifyTake 30
|
||||||
|
#define SYSTEM_CALL_xTaskGenericNotifyStateClear 31
|
||||||
|
#define SYSTEM_CALL_ulTaskGenericNotifyValueClear 32
|
||||||
|
#define SYSTEM_CALL_xQueueGenericSend 33
|
||||||
|
#define SYSTEM_CALL_uxQueueMessagesWaiting 34
|
||||||
|
#define SYSTEM_CALL_uxQueueSpacesAvailable 35
|
||||||
|
#define SYSTEM_CALL_xQueueReceive 36
|
||||||
|
#define SYSTEM_CALL_xQueuePeek 37
|
||||||
|
#define SYSTEM_CALL_xQueueSemaphoreTake 38
|
||||||
|
#define SYSTEM_CALL_xQueueGetMutexHolder 39
|
||||||
|
#define SYSTEM_CALL_xQueueTakeMutexRecursive 40
|
||||||
|
#define SYSTEM_CALL_xQueueGiveMutexRecursive 41
|
||||||
|
#define SYSTEM_CALL_xQueueSelectFromSet 42
|
||||||
|
#define SYSTEM_CALL_xQueueAddToSet 43
|
||||||
|
#define SYSTEM_CALL_vQueueAddToRegistry 44
|
||||||
|
#define SYSTEM_CALL_vQueueUnregisterQueue 45
|
||||||
|
#define SYSTEM_CALL_pcQueueGetName 46
|
||||||
|
#define SYSTEM_CALL_pvTimerGetTimerID 47
|
||||||
|
#define SYSTEM_CALL_vTimerSetTimerID 48
|
||||||
|
#define SYSTEM_CALL_xTimerIsTimerActive 49
|
||||||
|
#define SYSTEM_CALL_xTimerGetTimerDaemonTaskHandle 50
|
||||||
|
#define SYSTEM_CALL_pcTimerGetName 51
|
||||||
|
#define SYSTEM_CALL_vTimerSetReloadMode 52
|
||||||
|
#define SYSTEM_CALL_xTimerGetReloadMode 53
|
||||||
|
#define SYSTEM_CALL_uxTimerGetReloadMode 54
|
||||||
|
#define SYSTEM_CALL_xTimerGetPeriod 55
|
||||||
|
#define SYSTEM_CALL_xTimerGetExpiryTime 56
|
||||||
|
#define SYSTEM_CALL_xEventGroupClearBits 57
|
||||||
|
#define SYSTEM_CALL_xEventGroupSetBits 58
|
||||||
|
#define SYSTEM_CALL_xEventGroupSync 59
|
||||||
|
#define SYSTEM_CALL_uxEventGroupGetNumber 60
|
||||||
|
#define SYSTEM_CALL_vEventGroupSetNumber 61
|
||||||
|
#define SYSTEM_CALL_xStreamBufferSend 62
|
||||||
|
#define SYSTEM_CALL_xStreamBufferReceive 63
|
||||||
|
#define SYSTEM_CALL_xStreamBufferIsFull 64
|
||||||
|
#define SYSTEM_CALL_xStreamBufferIsEmpty 65
|
||||||
|
#define SYSTEM_CALL_xStreamBufferSpacesAvailable 66
|
||||||
|
#define SYSTEM_CALL_xStreamBufferBytesAvailable 67
|
||||||
|
#define SYSTEM_CALL_xStreamBufferSetTriggerLevel 68
|
||||||
|
#define SYSTEM_CALL_xStreamBufferNextMessageLengthBytes 69
|
||||||
|
#define NUM_SYSTEM_CALLS 70 /* Total number of system calls. */
|
||||||
|
|
||||||
|
#endif /* MPU_SYSCALL_NUMBERS_H */
|
||||||
@@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MPU_WRAPPERS_H
|
||||||
|
#define MPU_WRAPPERS_H
|
||||||
|
|
||||||
|
/* This file redefines API functions to be called through a wrapper macro, but
|
||||||
|
* only for ports that are using the MPU. */
|
||||||
|
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||||
|
|
||||||
|
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is
|
||||||
|
* included from queue.c or task.c to prevent it from having an effect within
|
||||||
|
* those files. */
|
||||||
|
#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map standard (non MPU) API functions to equivalents that start
|
||||||
|
* "MPU_". This will cause the application code to call the MPU_
|
||||||
|
* version, which wraps the non-MPU version with privilege promoting
|
||||||
|
* then demoting code, so the kernel code always runs will full
|
||||||
|
* privileges.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Map standard task.h API functions to the MPU equivalents. */
|
||||||
|
#define vTaskDelay MPU_vTaskDelay
|
||||||
|
#define xTaskDelayUntil MPU_xTaskDelayUntil
|
||||||
|
#define xTaskAbortDelay MPU_xTaskAbortDelay
|
||||||
|
#define uxTaskPriorityGet MPU_uxTaskPriorityGet
|
||||||
|
#define eTaskGetState MPU_eTaskGetState
|
||||||
|
#define vTaskGetInfo MPU_vTaskGetInfo
|
||||||
|
#define vTaskSuspend MPU_vTaskSuspend
|
||||||
|
#define vTaskResume MPU_vTaskResume
|
||||||
|
#define xTaskGetTickCount MPU_xTaskGetTickCount
|
||||||
|
#define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks
|
||||||
|
#define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark
|
||||||
|
#define uxTaskGetStackHighWaterMark2 MPU_uxTaskGetStackHighWaterMark2
|
||||||
|
#define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag
|
||||||
|
#define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag
|
||||||
|
#define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer
|
||||||
|
#define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer
|
||||||
|
#define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle
|
||||||
|
#define uxTaskGetSystemState MPU_uxTaskGetSystemState
|
||||||
|
#define ulTaskGetIdleRunTimeCounter MPU_ulTaskGetIdleRunTimeCounter
|
||||||
|
#define ulTaskGetIdleRunTimePercent MPU_ulTaskGetIdleRunTimePercent
|
||||||
|
#define xTaskGenericNotify MPU_xTaskGenericNotify
|
||||||
|
#define xTaskGenericNotifyWait MPU_xTaskGenericNotifyWait
|
||||||
|
#define ulTaskGenericNotifyTake MPU_ulTaskGenericNotifyTake
|
||||||
|
#define xTaskGenericNotifyStateClear MPU_xTaskGenericNotifyStateClear
|
||||||
|
#define ulTaskGenericNotifyValueClear MPU_ulTaskGenericNotifyValueClear
|
||||||
|
#define vTaskSetTimeOutState MPU_vTaskSetTimeOutState
|
||||||
|
#define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut
|
||||||
|
#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
|
||||||
|
#define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
|
||||||
|
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||||
|
#define ulTaskGetRunTimeCounter MPU_ulTaskGetRunTimeCounter
|
||||||
|
#define ulTaskGetRunTimePercent MPU_ulTaskGetRunTimePercent
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
/* Privileged only wrappers for Task APIs. These are needed so that
|
||||||
|
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||||
|
* with all the APIs. */
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 1 )
|
||||||
|
|
||||||
|
/* These are not needed in v2 because they do not take a task
|
||||||
|
* handle and therefore, no lookup is needed. Needed in v1 because
|
||||||
|
* these are available as system calls in v1. */
|
||||||
|
#define vTaskGetRunTimeStatistics MPU_vTaskGetRunTimeStatistics
|
||||||
|
#define vTaskListTasks MPU_vTaskListTasks
|
||||||
|
#define vTaskSuspendAll MPU_vTaskSuspendAll
|
||||||
|
#define xTaskCatchUpTicks MPU_xTaskCatchUpTicks
|
||||||
|
#define xTaskResumeAll MPU_xTaskResumeAll
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
|
||||||
|
|
||||||
|
#define xTaskCreate MPU_xTaskCreate
|
||||||
|
#define xTaskCreateStatic MPU_xTaskCreateStatic
|
||||||
|
#define vTaskDelete MPU_vTaskDelete
|
||||||
|
#define vTaskPrioritySet MPU_vTaskPrioritySet
|
||||||
|
#define xTaskGetHandle MPU_xTaskGetHandle
|
||||||
|
#define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook
|
||||||
|
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||||
|
#define pcTaskGetName MPU_pcTaskGetName
|
||||||
|
#define xTaskCreateRestricted MPU_xTaskCreateRestricted
|
||||||
|
#define xTaskCreateRestrictedStatic MPU_xTaskCreateRestrictedStatic
|
||||||
|
#define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions
|
||||||
|
#define xTaskGetStaticBuffers MPU_xTaskGetStaticBuffers
|
||||||
|
#define uxTaskPriorityGetFromISR MPU_uxTaskPriorityGetFromISR
|
||||||
|
#define uxTaskBasePriorityGet MPU_uxTaskBasePriorityGet
|
||||||
|
#define uxTaskBasePriorityGetFromISR MPU_uxTaskBasePriorityGetFromISR
|
||||||
|
#define xTaskResumeFromISR MPU_xTaskResumeFromISR
|
||||||
|
#define xTaskGetApplicationTaskTagFromISR MPU_xTaskGetApplicationTaskTagFromISR
|
||||||
|
#define xTaskGenericNotifyFromISR MPU_xTaskGenericNotifyFromISR
|
||||||
|
#define vTaskGenericNotifyGiveFromISR MPU_vTaskGenericNotifyGiveFromISR
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
/* Map standard queue.h API functions to the MPU equivalents. */
|
||||||
|
#define xQueueGenericSend MPU_xQueueGenericSend
|
||||||
|
#define xQueueReceive MPU_xQueueReceive
|
||||||
|
#define xQueuePeek MPU_xQueuePeek
|
||||||
|
#define xQueueSemaphoreTake MPU_xQueueSemaphoreTake
|
||||||
|
#define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
|
||||||
|
#define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable
|
||||||
|
#define xQueueGetMutexHolder MPU_xQueueGetMutexHolder
|
||||||
|
#define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive
|
||||||
|
#define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive
|
||||||
|
#define xQueueAddToSet MPU_xQueueAddToSet
|
||||||
|
#define xQueueSelectFromSet MPU_xQueueSelectFromSet
|
||||||
|
|
||||||
|
#if ( configQUEUE_REGISTRY_SIZE > 0 )
|
||||||
|
#define vQueueAddToRegistry MPU_vQueueAddToRegistry
|
||||||
|
#define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
|
||||||
|
#define pcQueueGetName MPU_pcQueueGetName
|
||||||
|
#endif /* #if ( configQUEUE_REGISTRY_SIZE > 0 ) */
|
||||||
|
|
||||||
|
/* Privileged only wrappers for Queue APIs. These are needed so that
|
||||||
|
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||||
|
* with all the APIs. */
|
||||||
|
#define vQueueDelete MPU_vQueueDelete
|
||||||
|
#define xQueueCreateMutex MPU_xQueueCreateMutex
|
||||||
|
#define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic
|
||||||
|
#define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore
|
||||||
|
#define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic
|
||||||
|
#define xQueueGenericCreate MPU_xQueueGenericCreate
|
||||||
|
#define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic
|
||||||
|
#define xQueueGenericReset MPU_xQueueGenericReset
|
||||||
|
#define xQueueCreateSet MPU_xQueueCreateSet
|
||||||
|
#define xQueueCreateSetStatic MPU_xQueueCreateSetStatic
|
||||||
|
#define xQueueRemoveFromSet MPU_xQueueRemoveFromSet
|
||||||
|
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||||
|
#define xQueueGenericGetStaticBuffers MPU_xQueueGenericGetStaticBuffers
|
||||||
|
#define xQueueGenericSendFromISR MPU_xQueueGenericSendFromISR
|
||||||
|
#define xQueueGiveFromISR MPU_xQueueGiveFromISR
|
||||||
|
#define xQueuePeekFromISR MPU_xQueuePeekFromISR
|
||||||
|
#define xQueueReceiveFromISR MPU_xQueueReceiveFromISR
|
||||||
|
#define xQueueIsQueueEmptyFromISR MPU_xQueueIsQueueEmptyFromISR
|
||||||
|
#define xQueueIsQueueFullFromISR MPU_xQueueIsQueueFullFromISR
|
||||||
|
#define uxQueueMessagesWaitingFromISR MPU_uxQueueMessagesWaitingFromISR
|
||||||
|
#define xQueueGetMutexHolderFromISR MPU_xQueueGetMutexHolderFromISR
|
||||||
|
#define xQueueSelectFromSetFromISR MPU_xQueueSelectFromSetFromISR
|
||||||
|
#endif /* if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
/* Map standard timer.h API functions to the MPU equivalents. */
|
||||||
|
#define pvTimerGetTimerID MPU_pvTimerGetTimerID
|
||||||
|
#define vTimerSetTimerID MPU_vTimerSetTimerID
|
||||||
|
#define xTimerIsTimerActive MPU_xTimerIsTimerActive
|
||||||
|
#define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle
|
||||||
|
#define xTimerGenericCommandFromTask MPU_xTimerGenericCommandFromTask
|
||||||
|
#define pcTimerGetName MPU_pcTimerGetName
|
||||||
|
#define vTimerSetReloadMode MPU_vTimerSetReloadMode
|
||||||
|
#define uxTimerGetReloadMode MPU_uxTimerGetReloadMode
|
||||||
|
#define xTimerGetPeriod MPU_xTimerGetPeriod
|
||||||
|
#define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
|
||||||
|
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||||
|
#define xTimerGetReloadMode MPU_xTimerGetReloadMode
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
/* Privileged only wrappers for Timer APIs. These are needed so that
|
||||||
|
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||||
|
* with all the APIs. */
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||||
|
#define xTimerCreate MPU_xTimerCreate
|
||||||
|
#define xTimerCreateStatic MPU_xTimerCreateStatic
|
||||||
|
#define xTimerGetStaticBuffer MPU_xTimerGetStaticBuffer
|
||||||
|
#define xTimerGenericCommandFromISR MPU_xTimerGenericCommandFromISR
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
/* Map standard event_group.h API functions to the MPU equivalents. */
|
||||||
|
#define xEventGroupWaitBits MPU_xEventGroupWaitBits
|
||||||
|
#define xEventGroupClearBits MPU_xEventGroupClearBits
|
||||||
|
#define xEventGroupSetBits MPU_xEventGroupSetBits
|
||||||
|
#define xEventGroupSync MPU_xEventGroupSync
|
||||||
|
|
||||||
|
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
#define uxEventGroupGetNumber MPU_uxEventGroupGetNumber
|
||||||
|
#define vEventGroupSetNumber MPU_vEventGroupSetNumber
|
||||||
|
#endif /* #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) */
|
||||||
|
|
||||||
|
/* Privileged only wrappers for Event Group APIs. These are needed so that
|
||||||
|
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||||
|
* with all the APIs. */
|
||||||
|
#define xEventGroupCreate MPU_xEventGroupCreate
|
||||||
|
#define xEventGroupCreateStatic MPU_xEventGroupCreateStatic
|
||||||
|
#define vEventGroupDelete MPU_vEventGroupDelete
|
||||||
|
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||||
|
#define xEventGroupGetStaticBuffer MPU_xEventGroupGetStaticBuffer
|
||||||
|
#define xEventGroupClearBitsFromISR MPU_xEventGroupClearBitsFromISR
|
||||||
|
#define xEventGroupSetBitsFromISR MPU_xEventGroupSetBitsFromISR
|
||||||
|
#define xEventGroupGetBitsFromISR MPU_xEventGroupGetBitsFromISR
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
/* Map standard message/stream_buffer.h API functions to the MPU
|
||||||
|
* equivalents. */
|
||||||
|
#define xStreamBufferSend MPU_xStreamBufferSend
|
||||||
|
#define xStreamBufferReceive MPU_xStreamBufferReceive
|
||||||
|
#define xStreamBufferIsFull MPU_xStreamBufferIsFull
|
||||||
|
#define xStreamBufferIsEmpty MPU_xStreamBufferIsEmpty
|
||||||
|
#define xStreamBufferSpacesAvailable MPU_xStreamBufferSpacesAvailable
|
||||||
|
#define xStreamBufferBytesAvailable MPU_xStreamBufferBytesAvailable
|
||||||
|
#define xStreamBufferSetTriggerLevel MPU_xStreamBufferSetTriggerLevel
|
||||||
|
#define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes
|
||||||
|
|
||||||
|
/* Privileged only wrappers for Stream Buffer APIs. These are needed so that
|
||||||
|
* the application can use opaque handles maintained in mpu_wrappers.c
|
||||||
|
* with all the APIs. */
|
||||||
|
|
||||||
|
#define xStreamBufferGenericCreate MPU_xStreamBufferGenericCreate
|
||||||
|
#define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic
|
||||||
|
#define vStreamBufferDelete MPU_vStreamBufferDelete
|
||||||
|
#define xStreamBufferReset MPU_xStreamBufferReset
|
||||||
|
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||||
|
#define xStreamBufferGetStaticBuffers MPU_xStreamBufferGetStaticBuffers
|
||||||
|
#define xStreamBufferSendFromISR MPU_xStreamBufferSendFromISR
|
||||||
|
#define xStreamBufferReceiveFromISR MPU_xStreamBufferReceiveFromISR
|
||||||
|
#define xStreamBufferSendCompletedFromISR MPU_xStreamBufferSendCompletedFromISR
|
||||||
|
#define xStreamBufferReceiveCompletedFromISR MPU_xStreamBufferReceiveCompletedFromISR
|
||||||
|
#define xStreamBufferResetFromISR MPU_xStreamBufferResetFromISR
|
||||||
|
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
#if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
|
||||||
|
|
||||||
|
#define vGrantAccessToTask( xTask, xTaskToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToGrantAccess ) )
|
||||||
|
#define vRevokeAccessToTask( xTask, xTaskToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToRevokeAccess ) )
|
||||||
|
|
||||||
|
#define vGrantAccessToSemaphore( xTask, xSemaphoreToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xSemaphoreToGrantAccess ) )
|
||||||
|
#define vRevokeAccessToSemaphore( xTask, xSemaphoreToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xSemaphoreToRevokeAccess ) )
|
||||||
|
|
||||||
|
#define vGrantAccessToQueue( xTask, xQueueToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueToGrantAccess ) )
|
||||||
|
#define vRevokeAccessToQueue( xTask, xQueueToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueToRevokeAccess ) )
|
||||||
|
|
||||||
|
#define vGrantAccessToQueueSet( xTask, xQueueSetToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueSetToGrantAccess ) )
|
||||||
|
#define vRevokeAccessToQueueSet( xTask, xQueueSetToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueSetToRevokeAccess ) )
|
||||||
|
|
||||||
|
#define vGrantAccessToEventGroup( xTask, xEventGroupToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xEventGroupToGrantAccess ) )
|
||||||
|
#define vRevokeAccessToEventGroup( xTask, xEventGroupToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xEventGroupToRevokeAccess ) )
|
||||||
|
|
||||||
|
#define vGrantAccessToStreamBuffer( xTask, xStreamBufferToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xStreamBufferToGrantAccess ) )
|
||||||
|
#define vRevokeAccessToStreamBuffer( xTask, xStreamBufferToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xStreamBufferToRevokeAccess ) )
|
||||||
|
|
||||||
|
#define vGrantAccessToMessageBuffer( xTask, xMessageBufferToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xMessageBufferToGrantAccess ) )
|
||||||
|
#define vRevokeAccessToMessageBuffer( xTask, xMessageBufferToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xMessageBufferToRevokeAccess ) )
|
||||||
|
|
||||||
|
#define vGrantAccessToTimer( xTask, xTimerToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xTimerToGrantAccess ) )
|
||||||
|
#define vRevokeAccessToTimer( xTask, xTimerToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xTimerToRevokeAccess ) )
|
||||||
|
|
||||||
|
#endif /* #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) */
|
||||||
|
|
||||||
|
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
|
||||||
|
|
||||||
|
#define PRIVILEGED_FUNCTION __attribute__( ( section( "privileged_functions" ) ) )
|
||||||
|
#define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
|
||||||
|
#define FREERTOS_SYSTEM_CALL __attribute__( ( section( "freertos_system_calls" ) ) )
|
||||||
|
|
||||||
|
#else /* portUSING_MPU_WRAPPERS */
|
||||||
|
|
||||||
|
#define PRIVILEGED_FUNCTION
|
||||||
|
#define PRIVILEGED_DATA
|
||||||
|
#define FREERTOS_SYSTEM_CALL
|
||||||
|
|
||||||
|
#endif /* portUSING_MPU_WRAPPERS */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* MPU_WRAPPERS_H */
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INC_NEWLIB_FREERTOS_H
|
||||||
|
#define INC_NEWLIB_FREERTOS_H
|
||||||
|
|
||||||
|
/* Note Newlib support has been included by popular demand, but is not
|
||||||
|
* used by the FreeRTOS maintainers themselves. FreeRTOS is not
|
||||||
|
* responsible for resulting newlib operation. User must be familiar with
|
||||||
|
* newlib and must provide system-wide implementations of the necessary
|
||||||
|
* stubs. Be warned that (at the time of writing) the current newlib design
|
||||||
|
* implements a system-wide malloc() that must be provided with locks.
|
||||||
|
*
|
||||||
|
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
|
||||||
|
* for additional information. */
|
||||||
|
|
||||||
|
#include <reent.h>
|
||||||
|
|
||||||
|
#define configUSE_C_RUNTIME_TLS_SUPPORT 1
|
||||||
|
|
||||||
|
#ifndef configTLS_BLOCK_TYPE
|
||||||
|
#define configTLS_BLOCK_TYPE struct _reent
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configINIT_TLS_BLOCK
|
||||||
|
#define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) _REENT_INIT_PTR( &( xTLSBlock ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configSET_TLS_BLOCK
|
||||||
|
#define configSET_TLS_BLOCK( xTLSBlock ) ( _impure_ptr = &( xTLSBlock ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configDEINIT_TLS_BLOCK
|
||||||
|
#define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* INC_NEWLIB_FREERTOS_H */
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INC_PICOLIBC_FREERTOS_H
|
||||||
|
#define INC_PICOLIBC_FREERTOS_H
|
||||||
|
|
||||||
|
/* Use picolibc TLS support to allocate space for __thread variables,
|
||||||
|
* initialize them at thread creation and set the TLS context at
|
||||||
|
* thread switch time.
|
||||||
|
*
|
||||||
|
* See the picolibc TLS docs:
|
||||||
|
* https://github.com/picolibc/picolibc/blob/main/doc/tls.md
|
||||||
|
* for additional information. */
|
||||||
|
|
||||||
|
#include <picotls.h>
|
||||||
|
|
||||||
|
#define configUSE_C_RUNTIME_TLS_SUPPORT 1
|
||||||
|
|
||||||
|
#define configTLS_BLOCK_TYPE void *
|
||||||
|
|
||||||
|
#define picolibcTLS_SIZE ( ( portPOINTER_SIZE_TYPE ) _tls_size() )
|
||||||
|
#define picolibcSTACK_ALIGNMENT_MASK ( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK )
|
||||||
|
|
||||||
|
#if __PICOLIBC_MAJOR__ > 1 || __PICOLIBC_MINOR__ >= 8
|
||||||
|
|
||||||
|
/* Picolibc 1.8 and newer have explicit alignment values provided
|
||||||
|
* by the _tls_align() inline */
|
||||||
|
#define picolibcTLS_ALIGNMENT_MASK ( ( portPOINTER_SIZE_TYPE ) ( _tls_align() - 1 ) )
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* For older Picolibc versions, use the general port alignment value */
|
||||||
|
#define picolibcTLS_ALIGNMENT_MASK ( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Allocate thread local storage block off the end of the
|
||||||
|
* stack. The picolibcTLS_SIZE macro returns the size (in
|
||||||
|
* bytes) of the total TLS area used by the application.
|
||||||
|
* Calculate the top of stack address. */
|
||||||
|
#if ( portSTACK_GROWTH < 0 )
|
||||||
|
|
||||||
|
#define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) \
|
||||||
|
do { \
|
||||||
|
xTLSBlock = ( void * ) ( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) - \
|
||||||
|
picolibcTLS_SIZE ) & \
|
||||||
|
~picolibcTLS_ALIGNMENT_MASK ); \
|
||||||
|
pxTopOfStack = ( StackType_t * ) ( ( ( ( portPOINTER_SIZE_TYPE ) xTLSBlock ) - 1 ) & \
|
||||||
|
~picolibcSTACK_ALIGNMENT_MASK ); \
|
||||||
|
_init_tls( xTLSBlock ); \
|
||||||
|
} while( 0 )
|
||||||
|
#else /* portSTACK_GROWTH */
|
||||||
|
#define configINIT_TLS_BLOCK( xTLSBlock, pxTopOfStack ) \
|
||||||
|
do { \
|
||||||
|
xTLSBlock = ( void * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack + \
|
||||||
|
picolibcTLS_ALIGNMENT_MASK ) & ~picolibcTLS_ALIGNMENT_MASK ); \
|
||||||
|
pxTopOfStack = ( StackType_t * ) ( ( ( ( ( portPOINTER_SIZE_TYPE ) xTLSBlock ) + \
|
||||||
|
picolibcTLS_SIZE ) + picolibcSTACK_ALIGNMENT_MASK ) & \
|
||||||
|
~picolibcSTACK_ALIGNMENT_MASK ); \
|
||||||
|
_init_tls( xTLSBlock ); \
|
||||||
|
} while( 0 )
|
||||||
|
#endif /* portSTACK_GROWTH */
|
||||||
|
|
||||||
|
#define configSET_TLS_BLOCK( xTLSBlock ) _set_tls( xTLSBlock )
|
||||||
|
|
||||||
|
#define configDEINIT_TLS_BLOCK( xTLSBlock )
|
||||||
|
|
||||||
|
#endif /* INC_PICOLIBC_FREERTOS_H */
|
||||||
@@ -0,0 +1,290 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Portable layer API. Each function must be defined for each port.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef PORTABLE_H
|
||||||
|
#define PORTABLE_H
|
||||||
|
|
||||||
|
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
|
||||||
|
* pre-processor definition was used to ensure the pre-processor found the correct
|
||||||
|
* portmacro.h file for the port being used. That scheme was deprecated in favour
|
||||||
|
* of setting the compiler's include path such that it found the correct
|
||||||
|
* portmacro.h file - removing the need for the constant and allowing the
|
||||||
|
* portmacro.h file to be located anywhere in relation to the port being used.
|
||||||
|
* Purely for reasons of backward compatibility the old method is still valid, but
|
||||||
|
* to make it clear that new projects should not use it, support for the port
|
||||||
|
* specific constants has been moved into the deprecated_definitions.h header
|
||||||
|
* file. */
|
||||||
|
#include "deprecated_definitions.h"
|
||||||
|
|
||||||
|
/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h
|
||||||
|
* did not result in a portmacro.h header file being included - and it should be
|
||||||
|
* included here. In this case the path to the correct portmacro.h header file
|
||||||
|
* must be set in the compiler's include path. */
|
||||||
|
#ifndef portENTER_CRITICAL
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if portBYTE_ALIGNMENT == 32
|
||||||
|
#define portBYTE_ALIGNMENT_MASK ( 0x001f )
|
||||||
|
#elif portBYTE_ALIGNMENT == 16
|
||||||
|
#define portBYTE_ALIGNMENT_MASK ( 0x000f )
|
||||||
|
#elif portBYTE_ALIGNMENT == 8
|
||||||
|
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||||
|
#elif portBYTE_ALIGNMENT == 4
|
||||||
|
#define portBYTE_ALIGNMENT_MASK ( 0x0003 )
|
||||||
|
#elif portBYTE_ALIGNMENT == 2
|
||||||
|
#define portBYTE_ALIGNMENT_MASK ( 0x0001 )
|
||||||
|
#elif portBYTE_ALIGNMENT == 1
|
||||||
|
#define portBYTE_ALIGNMENT_MASK ( 0x0000 )
|
||||||
|
#else /* if portBYTE_ALIGNMENT == 32 */
|
||||||
|
#error "Invalid portBYTE_ALIGNMENT definition"
|
||||||
|
#endif /* if portBYTE_ALIGNMENT == 32 */
|
||||||
|
|
||||||
|
#ifndef portUSING_MPU_WRAPPERS
|
||||||
|
#define portUSING_MPU_WRAPPERS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef portNUM_CONFIGURABLE_REGIONS
|
||||||
|
#define portNUM_CONFIGURABLE_REGIONS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef portHAS_STACK_OVERFLOW_CHECKING
|
||||||
|
#define portHAS_STACK_OVERFLOW_CHECKING 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef portARCH_NAME
|
||||||
|
#define portARCH_NAME NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef portBASE_TYPE_ENTER_CRITICAL
|
||||||
|
#define portBASE_TYPE_ENTER_CRITICAL() taskENTER_CRITICAL()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef portBASE_TYPE_EXIT_CRITICAL
|
||||||
|
#define portBASE_TYPE_EXIT_CRITICAL() taskEXIT_CRITICAL()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configSTACK_DEPTH_TYPE
|
||||||
|
#define configSTACK_DEPTH_TYPE StackType_t
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configSTACK_ALLOCATION_FROM_SEPARATE_HEAP
|
||||||
|
/* Defaults to 0 for backward compatibility. */
|
||||||
|
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mpu_wrappers.h"
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the stack of a new task so it is ready to be placed under the
|
||||||
|
* scheduler control. The registers have to be placed on the stack in
|
||||||
|
* the order that the port expects to find them.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||||
|
#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
|
||||||
|
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||||
|
StackType_t * pxEndOfStack,
|
||||||
|
TaskFunction_t pxCode,
|
||||||
|
void * pvParameters,
|
||||||
|
BaseType_t xRunPrivileged,
|
||||||
|
xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION;
|
||||||
|
#else
|
||||||
|
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||||
|
TaskFunction_t pxCode,
|
||||||
|
void * pvParameters,
|
||||||
|
BaseType_t xRunPrivileged,
|
||||||
|
xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif /* if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) */
|
||||||
|
#else /* if ( portUSING_MPU_WRAPPERS == 1 ) */
|
||||||
|
#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
|
||||||
|
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||||
|
StackType_t * pxEndOfStack,
|
||||||
|
TaskFunction_t pxCode,
|
||||||
|
void * pvParameters ) PRIVILEGED_FUNCTION;
|
||||||
|
#else
|
||||||
|
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||||
|
TaskFunction_t pxCode,
|
||||||
|
void * pvParameters ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif
|
||||||
|
#endif /* if ( portUSING_MPU_WRAPPERS == 1 ) */
|
||||||
|
|
||||||
|
/* Used by heap_5.c to define the start address and size of each memory region
|
||||||
|
* that together comprise the total FreeRTOS heap space. */
|
||||||
|
typedef struct HeapRegion
|
||||||
|
{
|
||||||
|
uint8_t * pucStartAddress;
|
||||||
|
size_t xSizeInBytes;
|
||||||
|
} HeapRegion_t;
|
||||||
|
|
||||||
|
/* Used to pass information about the heap out of vPortGetHeapStats(). */
|
||||||
|
typedef struct xHeapStats
|
||||||
|
{
|
||||||
|
size_t xAvailableHeapSpaceInBytes; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */
|
||||||
|
size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
|
||||||
|
size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
|
||||||
|
size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */
|
||||||
|
size_t xMinimumEverFreeBytesRemaining; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */
|
||||||
|
size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */
|
||||||
|
size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */
|
||||||
|
} HeapStats_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to define multiple heap regions for use by heap_5.c. This function
|
||||||
|
* must be called before any calls to pvPortMalloc() - not creating a task,
|
||||||
|
* queue, semaphore, mutex, software timer, event group, etc. will result in
|
||||||
|
* pvPortMalloc being called.
|
||||||
|
*
|
||||||
|
* pxHeapRegions passes in an array of HeapRegion_t structures - each of which
|
||||||
|
* defines a region of memory that can be used as the heap. The array is
|
||||||
|
* terminated by a HeapRegions_t structure that has a size of 0. The region
|
||||||
|
* with the lowest start address must appear first in the array.
|
||||||
|
*/
|
||||||
|
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a HeapStats_t structure filled with information about the current
|
||||||
|
* heap state.
|
||||||
|
*/
|
||||||
|
void vPortGetHeapStats( HeapStats_t * pxHeapStats );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map to the memory management routines required for the port.
|
||||||
|
*/
|
||||||
|
void * pvPortMalloc( size_t xWantedSize ) PRIVILEGED_FUNCTION;
|
||||||
|
void * pvPortCalloc( size_t xNum,
|
||||||
|
size_t xSize ) PRIVILEGED_FUNCTION;
|
||||||
|
void vPortFree( void * pv ) PRIVILEGED_FUNCTION;
|
||||||
|
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
|
||||||
|
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||||
|
void xPortResetHeapMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
#if ( configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1 )
|
||||||
|
void * pvPortMallocStack( size_t xSize ) PRIVILEGED_FUNCTION;
|
||||||
|
void vPortFreeStack( void * pv ) PRIVILEGED_FUNCTION;
|
||||||
|
#else
|
||||||
|
#define pvPortMallocStack pvPortMalloc
|
||||||
|
#define vPortFreeStack vPortFree
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function resets the internal state of the heap module. It must be called
|
||||||
|
* by the application before restarting the scheduler.
|
||||||
|
*/
|
||||||
|
void vPortHeapResetState( void ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* task.h
|
||||||
|
* @code{c}
|
||||||
|
* void vApplicationMallocFailedHook( void )
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* This hook function is called when allocation failed.
|
||||||
|
*/
|
||||||
|
void vApplicationMallocFailedHook( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the hardware ready for the scheduler to take control. This generally
|
||||||
|
* sets up a tick interrupt and sets timers for the correct tick frequency.
|
||||||
|
*/
|
||||||
|
BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Undo any hardware/ISR setup that was performed by xPortStartScheduler() so
|
||||||
|
* the hardware is left in its original condition after the scheduler stops
|
||||||
|
* executing.
|
||||||
|
*/
|
||||||
|
void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The structures and methods of manipulating the MPU are contained within the
|
||||||
|
* port layer.
|
||||||
|
*
|
||||||
|
* Fills the xMPUSettings structure with the memory region information
|
||||||
|
* contained in xRegions.
|
||||||
|
*/
|
||||||
|
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||||
|
struct xMEMORY_REGION;
|
||||||
|
void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
|
||||||
|
const struct xMEMORY_REGION * const xRegions,
|
||||||
|
StackType_t * pxBottomOfStack,
|
||||||
|
configSTACK_DEPTH_TYPE uxStackDepth ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the calling task is authorized to access the given buffer.
|
||||||
|
*
|
||||||
|
* @param pvBuffer The buffer which the calling task wants to access.
|
||||||
|
* @param ulBufferLength The length of the pvBuffer.
|
||||||
|
* @param ulAccessRequested The permissions that the calling task wants.
|
||||||
|
*
|
||||||
|
* @return pdTRUE if the calling task is authorized to access the buffer,
|
||||||
|
* pdFALSE otherwise.
|
||||||
|
*/
|
||||||
|
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||||
|
BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
|
||||||
|
uint32_t ulBufferLength,
|
||||||
|
uint32_t ulAccessRequested ) PRIVILEGED_FUNCTION;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the calling task is authorized to access the given kernel object.
|
||||||
|
*
|
||||||
|
* @param lInternalIndexOfKernelObject The index of the kernel object in the kernel
|
||||||
|
* object handle pool.
|
||||||
|
*
|
||||||
|
* @return pdTRUE if the calling task is authorized to access the kernel object,
|
||||||
|
* pdFALSE otherwise.
|
||||||
|
*/
|
||||||
|
#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
|
||||||
|
BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTABLE_H */
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PROJDEFS_H
|
||||||
|
#define PROJDEFS_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defines the prototype to which task functions must conform. Defined in this
|
||||||
|
* file to ensure the type is known before portable.h is included.
|
||||||
|
*/
|
||||||
|
typedef void (* TaskFunction_t)( void * arg );
|
||||||
|
|
||||||
|
/* Converts a time in milliseconds to a time in ticks. This macro can be
|
||||||
|
* overridden by a macro of the same name defined in FreeRTOSConfig.h in case the
|
||||||
|
* definition here is not suitable for your application. */
|
||||||
|
#ifndef pdMS_TO_TICKS
|
||||||
|
#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( uint64_t ) ( xTimeInMs ) * ( uint64_t ) configTICK_RATE_HZ ) / ( uint64_t ) 1000U ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Converts a time in ticks to a time in milliseconds. This macro can be
|
||||||
|
* overridden by a macro of the same name defined in FreeRTOSConfig.h in case the
|
||||||
|
* definition here is not suitable for your application. */
|
||||||
|
#ifndef pdTICKS_TO_MS
|
||||||
|
#define pdTICKS_TO_MS( xTimeInTicks ) ( ( TickType_t ) ( ( ( uint64_t ) ( xTimeInTicks ) * ( uint64_t ) 1000U ) / ( uint64_t ) configTICK_RATE_HZ ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define pdFALSE ( ( BaseType_t ) 0 )
|
||||||
|
#define pdTRUE ( ( BaseType_t ) 1 )
|
||||||
|
#define pdFALSE_SIGNED ( ( BaseType_t ) 0 )
|
||||||
|
#define pdTRUE_SIGNED ( ( BaseType_t ) 1 )
|
||||||
|
#define pdFALSE_UNSIGNED ( ( UBaseType_t ) 0 )
|
||||||
|
#define pdTRUE_UNSIGNED ( ( UBaseType_t ) 1 )
|
||||||
|
|
||||||
|
#define pdPASS ( pdTRUE )
|
||||||
|
#define pdFAIL ( pdFALSE )
|
||||||
|
#define errQUEUE_EMPTY ( ( BaseType_t ) 0 )
|
||||||
|
#define errQUEUE_FULL ( ( BaseType_t ) 0 )
|
||||||
|
|
||||||
|
/* FreeRTOS error definitions. */
|
||||||
|
#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 )
|
||||||
|
#define errQUEUE_BLOCKED ( -4 )
|
||||||
|
#define errQUEUE_YIELD ( -5 )
|
||||||
|
|
||||||
|
/* Macros used for basic data corruption checks. */
|
||||||
|
#ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES
|
||||||
|
#define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||||
|
#define pdINTEGRITY_CHECK_VALUE 0x5a5a
|
||||||
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||||
|
#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL
|
||||||
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS )
|
||||||
|
#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5a5a5a5a5aULL
|
||||||
|
#else
|
||||||
|
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
|
||||||
|
* itself. */
|
||||||
|
#define pdFREERTOS_ERRNO_NONE 0 /* No errors */
|
||||||
|
#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
|
||||||
|
#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */
|
||||||
|
#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */
|
||||||
|
#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */
|
||||||
|
#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */
|
||||||
|
#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */
|
||||||
|
#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */
|
||||||
|
#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */
|
||||||
|
#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */
|
||||||
|
#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */
|
||||||
|
#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */
|
||||||
|
#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */
|
||||||
|
#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */
|
||||||
|
#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */
|
||||||
|
#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */
|
||||||
|
#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */
|
||||||
|
#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */
|
||||||
|
#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */
|
||||||
|
#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */
|
||||||
|
#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */
|
||||||
|
#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */
|
||||||
|
#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */
|
||||||
|
#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */
|
||||||
|
#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */
|
||||||
|
#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */
|
||||||
|
#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */
|
||||||
|
#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||||
|
#define pdFREERTOS_ERRNO_EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||||
|
#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
|
||||||
|
#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
|
||||||
|
#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
|
||||||
|
#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */
|
||||||
|
#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */
|
||||||
|
#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */
|
||||||
|
#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */
|
||||||
|
#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */
|
||||||
|
#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */
|
||||||
|
#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */
|
||||||
|
#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */
|
||||||
|
#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
|
||||||
|
|
||||||
|
/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
|
||||||
|
* itself. */
|
||||||
|
#define pdFREERTOS_LITTLE_ENDIAN 0
|
||||||
|
#define pdFREERTOS_BIG_ENDIAN 1
|
||||||
|
|
||||||
|
/* Re-defining endian values for generic naming. */
|
||||||
|
#define pdLITTLE_ENDIAN pdFREERTOS_LITTLE_ENDIAN
|
||||||
|
#define pdBIG_ENDIAN pdFREERTOS_BIG_ENDIAN
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* PROJDEFS_H */
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STACK_MACROS_H
|
||||||
|
#define STACK_MACROS_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call the stack overflow hook function if the stack of the task being swapped
|
||||||
|
* out is currently overflowed, or looks like it might have overflowed in the
|
||||||
|
* past.
|
||||||
|
*
|
||||||
|
* Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
|
||||||
|
* the current stack state only - comparing the current top of stack value to
|
||||||
|
* the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
|
||||||
|
* will also cause the last few stack bytes to be checked to ensure the value
|
||||||
|
* to which the bytes were set when the task was created have not been
|
||||||
|
* overwritten. Note this second test does not guarantee that an overflowed
|
||||||
|
* stack will always be recognised.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* portSTACK_LIMIT_PADDING is a number of extra words to consider to be in
|
||||||
|
* use on the stack.
|
||||||
|
*/
|
||||||
|
#ifndef portSTACK_LIMIT_PADDING
|
||||||
|
#define portSTACK_LIMIT_PADDING 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Stack overflow check is not straight forward to implement for MPU ports
|
||||||
|
* because of the following reasons:
|
||||||
|
* 1. The context is stored in TCB and as a result, pxTopOfStack member points
|
||||||
|
* to the context location in TCB.
|
||||||
|
* 2. System calls are executed on a separate privileged only stack.
|
||||||
|
*
|
||||||
|
* It is still okay because an MPU region is used to protect task stack which
|
||||||
|
* means task stack overflow will trigger an MPU fault for unprivileged tasks.
|
||||||
|
* Additionally, architectures with hardware stack overflow checking support
|
||||||
|
* (such as Armv8-M) will trigger a fault when a task's stack overflows.
|
||||||
|
*/
|
||||||
|
#if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) && ( portUSING_MPU_WRAPPERS != 1 ) )
|
||||||
|
|
||||||
|
/* Only the current stack state is to be checked. */
|
||||||
|
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||||
|
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \
|
||||||
|
{ \
|
||||||
|
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
|
||||||
|
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
|
||||||
|
} \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) && ( portUSING_MPU_WRAPPERS != 1 ) )
|
||||||
|
|
||||||
|
/* Only the current stack state is to be checked. */
|
||||||
|
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||||
|
if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \
|
||||||
|
{ \
|
||||||
|
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
|
||||||
|
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
|
||||||
|
} \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) && ( portUSING_MPU_WRAPPERS != 1 ) )
|
||||||
|
|
||||||
|
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
|
||||||
|
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5U; \
|
||||||
|
\
|
||||||
|
if( ( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) || \
|
||||||
|
( pulStack[ 0 ] != ulCheckValue ) || \
|
||||||
|
( pulStack[ 1 ] != ulCheckValue ) || \
|
||||||
|
( pulStack[ 2 ] != ulCheckValue ) || \
|
||||||
|
( pulStack[ 3 ] != ulCheckValue ) ) \
|
||||||
|
{ \
|
||||||
|
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
|
||||||
|
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
|
||||||
|
} \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) && ( portUSING_MPU_WRAPPERS != 1 ) )
|
||||||
|
|
||||||
|
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
|
||||||
|
static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||||
|
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||||
|
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||||
|
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||||
|
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
|
||||||
|
\
|
||||||
|
pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
|
||||||
|
\
|
||||||
|
if( ( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) || \
|
||||||
|
( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) ) \
|
||||||
|
{ \
|
||||||
|
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
|
||||||
|
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
|
||||||
|
} \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Remove stack overflow macro if not being used. */
|
||||||
|
#ifndef taskCHECK_FOR_STACK_OVERFLOW
|
||||||
|
#define taskCHECK_FOR_STACK_OVERFLOW()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* STACK_MACROS_H */
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FREERTOS_STDINT
|
||||||
|
#define FREERTOS_STDINT
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions
|
||||||
|
* necessary to build the FreeRTOS code. It is provided to allow FreeRTOS to be
|
||||||
|
* built using compilers that do not provide their own stdint.h definition.
|
||||||
|
*
|
||||||
|
* To use this file:
|
||||||
|
*
|
||||||
|
* 1) Copy this file into the directory that contains your FreeRTOSConfig.h
|
||||||
|
* header file, as that directory will already be in the compiler's include
|
||||||
|
* path.
|
||||||
|
*
|
||||||
|
* 2) Rename the copied file stdint.h.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef signed char int8_t;
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef short int16_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef long int32_t;
|
||||||
|
typedef unsigned long uint32_t;
|
||||||
|
|
||||||
|
#ifndef SIZE_MAX
|
||||||
|
#define SIZE_MAX ( ( size_t ) -1 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* FREERTOS_STDINT */
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||||
|
* all the API functions to use the MPU wrappers. That should only be done when
|
||||||
|
* task.h is included from an application file. */
|
||||||
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
/* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be
|
||||||
|
* defined for the header files above, but not in this file, in order to
|
||||||
|
* generate the correct privileged Vs unprivileged linkage and placement. */
|
||||||
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* PUBLIC LIST API documented in list.h
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vListInitialise( List_t * const pxList )
|
||||||
|
{
|
||||||
|
traceENTER_vListInitialise( pxList );
|
||||||
|
|
||||||
|
/* The list structure contains a list item which is used to mark the
|
||||||
|
* end of the list. To initialise the list the list end is inserted
|
||||||
|
* as the only list entry. */
|
||||||
|
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );
|
||||||
|
|
||||||
|
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );
|
||||||
|
|
||||||
|
/* The list end value is the highest possible value in the list to
|
||||||
|
* ensure it remains at the end of the list. */
|
||||||
|
pxList->xListEnd.xItemValue = portMAX_DELAY;
|
||||||
|
|
||||||
|
/* The list end next and previous pointers point to itself so we know
|
||||||
|
* when the list is empty. */
|
||||||
|
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
|
||||||
|
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
|
||||||
|
|
||||||
|
/* Initialize the remaining fields of xListEnd when it is a proper ListItem_t */
|
||||||
|
#if ( configUSE_MINI_LIST_ITEM == 0 )
|
||||||
|
{
|
||||||
|
pxList->xListEnd.pvOwner = NULL;
|
||||||
|
pxList->xListEnd.pxContainer = NULL;
|
||||||
|
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
|
||||||
|
|
||||||
|
/* Write known values into the list if
|
||||||
|
* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
|
||||||
|
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
|
||||||
|
|
||||||
|
traceRETURN_vListInitialise();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vListInitialiseItem( ListItem_t * const pxItem )
|
||||||
|
{
|
||||||
|
traceENTER_vListInitialiseItem( pxItem );
|
||||||
|
|
||||||
|
/* Make sure the list item is not recorded as being on a list. */
|
||||||
|
pxItem->pxContainer = NULL;
|
||||||
|
|
||||||
|
/* Write known values into the list item if
|
||||||
|
* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||||
|
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
|
||||||
|
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
|
||||||
|
|
||||||
|
traceRETURN_vListInitialiseItem();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vListInsertEnd( List_t * const pxList,
|
||||||
|
ListItem_t * const pxNewListItem )
|
||||||
|
{
|
||||||
|
ListItem_t * const pxIndex = pxList->pxIndex;
|
||||||
|
|
||||||
|
traceENTER_vListInsertEnd( pxList, pxNewListItem );
|
||||||
|
|
||||||
|
/* Only effective when configASSERT() is also defined, these tests may catch
|
||||||
|
* the list data structures being overwritten in memory. They will not catch
|
||||||
|
* data errors caused by incorrect configuration or use of FreeRTOS. */
|
||||||
|
listTEST_LIST_INTEGRITY( pxList );
|
||||||
|
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
|
||||||
|
|
||||||
|
/* Insert a new list item into pxList, but rather than sort the list,
|
||||||
|
* makes the new list item the last item to be removed by a call to
|
||||||
|
* listGET_OWNER_OF_NEXT_ENTRY(). */
|
||||||
|
pxNewListItem->pxNext = pxIndex;
|
||||||
|
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
|
||||||
|
|
||||||
|
/* Only used during decision coverage testing. */
|
||||||
|
mtCOVERAGE_TEST_DELAY();
|
||||||
|
|
||||||
|
pxIndex->pxPrevious->pxNext = pxNewListItem;
|
||||||
|
pxIndex->pxPrevious = pxNewListItem;
|
||||||
|
|
||||||
|
/* Remember which list the item is in. */
|
||||||
|
pxNewListItem->pxContainer = pxList;
|
||||||
|
|
||||||
|
( pxList->uxNumberOfItems ) = ( UBaseType_t ) ( pxList->uxNumberOfItems + 1U );
|
||||||
|
|
||||||
|
traceRETURN_vListInsertEnd();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vListInsert( List_t * const pxList,
|
||||||
|
ListItem_t * const pxNewListItem )
|
||||||
|
{
|
||||||
|
ListItem_t * pxIterator;
|
||||||
|
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
|
||||||
|
|
||||||
|
traceENTER_vListInsert( pxList, pxNewListItem );
|
||||||
|
|
||||||
|
/* Only effective when configASSERT() is also defined, these tests may catch
|
||||||
|
* the list data structures being overwritten in memory. They will not catch
|
||||||
|
* data errors caused by incorrect configuration or use of FreeRTOS. */
|
||||||
|
listTEST_LIST_INTEGRITY( pxList );
|
||||||
|
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
|
||||||
|
|
||||||
|
/* Insert the new list item into the list, sorted in xItemValue order.
|
||||||
|
*
|
||||||
|
* If the list already contains a list item with the same item value then the
|
||||||
|
* new list item should be placed after it. This ensures that TCBs which are
|
||||||
|
* stored in ready lists (all of which have the same xItemValue value) get a
|
||||||
|
* share of the CPU. However, if the xItemValue is the same as the back marker
|
||||||
|
* the iteration loop below will not end. Therefore the value is checked
|
||||||
|
* first, and the algorithm slightly modified if necessary. */
|
||||||
|
if( xValueOfInsertion == portMAX_DELAY )
|
||||||
|
{
|
||||||
|
pxIterator = pxList->xListEnd.pxPrevious;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* *** NOTE ***********************************************************
|
||||||
|
* If you find your application is crashing here then likely causes are
|
||||||
|
* listed below. In addition see https://www.freertos.org/Why-FreeRTOS/FAQs for
|
||||||
|
* more tips, and ensure configASSERT() is defined!
|
||||||
|
* https://www.FreeRTOS.org/a00110.html#configASSERT
|
||||||
|
*
|
||||||
|
* 1) Stack overflow -
|
||||||
|
* see https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html
|
||||||
|
* 2) Incorrect interrupt priority assignment, especially on Cortex-M
|
||||||
|
* parts where numerically high priority values denote low actual
|
||||||
|
* interrupt priorities, which can seem counter intuitive. See
|
||||||
|
* https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html and the definition
|
||||||
|
* of configMAX_SYSCALL_INTERRUPT_PRIORITY on
|
||||||
|
* https://www.FreeRTOS.org/a00110.html
|
||||||
|
* 3) Calling an API function from within a critical section or when
|
||||||
|
* the scheduler is suspended, or calling an API function that does
|
||||||
|
* not end in "FromISR" from an interrupt.
|
||||||
|
* 4) Using a queue or semaphore before it has been initialised or
|
||||||
|
* before the scheduler has been started (are interrupts firing
|
||||||
|
* before vTaskStartScheduler() has been called?).
|
||||||
|
* 5) If the FreeRTOS port supports interrupt nesting then ensure that
|
||||||
|
* the priority of the tick interrupt is at or below
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext )
|
||||||
|
{
|
||||||
|
/* There is nothing to do here, just iterating to the wanted
|
||||||
|
* insertion position.
|
||||||
|
* IF YOU FIND YOUR CODE STUCK HERE, SEE THE NOTE JUST ABOVE.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pxNewListItem->pxNext = pxIterator->pxNext;
|
||||||
|
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
|
||||||
|
pxNewListItem->pxPrevious = pxIterator;
|
||||||
|
pxIterator->pxNext = pxNewListItem;
|
||||||
|
|
||||||
|
/* Remember which list the item is in. This allows fast removal of the
|
||||||
|
* item later. */
|
||||||
|
pxNewListItem->pxContainer = pxList;
|
||||||
|
|
||||||
|
( pxList->uxNumberOfItems ) = ( UBaseType_t ) ( pxList->uxNumberOfItems + 1U );
|
||||||
|
|
||||||
|
traceRETURN_vListInsert();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
|
||||||
|
{
|
||||||
|
/* The list item knows which list it is in. Obtain the list from the list
|
||||||
|
* item. */
|
||||||
|
List_t * const pxList = pxItemToRemove->pxContainer;
|
||||||
|
|
||||||
|
traceENTER_uxListRemove( pxItemToRemove );
|
||||||
|
|
||||||
|
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
|
||||||
|
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
|
||||||
|
|
||||||
|
/* Only used during decision coverage testing. */
|
||||||
|
mtCOVERAGE_TEST_DELAY();
|
||||||
|
|
||||||
|
/* Make sure the index is left pointing to a valid item. */
|
||||||
|
if( pxList->pxIndex == pxItemToRemove )
|
||||||
|
{
|
||||||
|
pxList->pxIndex = pxItemToRemove->pxPrevious;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
pxItemToRemove->pxContainer = NULL;
|
||||||
|
( pxList->uxNumberOfItems ) = ( UBaseType_t ) ( pxList->uxNumberOfItems - 1U );
|
||||||
|
|
||||||
|
traceRETURN_uxListRemove( pxList->uxNumberOfItems );
|
||||||
|
|
||||||
|
return pxList->uxNumberOfItems;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
The FreeRTOS GCC port layer also builds and works with the ARMClang compiler.
|
||||||
|
To use the ARMClang compiler build the port files from FreeRTOS/Source/portable/GCC.
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
This directory tree contains the master copy of the FreeRTOS Armv8-M and
|
||||||
|
Armv8.1-M ports.
|
||||||
|
Do not use the files located here! These file are copied into separate
|
||||||
|
FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3]_NNN directories
|
||||||
|
prior to each FreeRTOS release.
|
||||||
|
|
||||||
|
If your Armv8-M and Armv8.1-M application uses TrustZone then use the files from the
|
||||||
|
FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3] directories.
|
||||||
|
|
||||||
|
If your Armv8-M and Armv8.1-M application does not use TrustZone then use the files from
|
||||||
|
the FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3]_NTZ directories.
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
#/*
|
||||||
|
# * FreeRTOS Kernel V11.3.0
|
||||||
|
# * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
# *
|
||||||
|
# * SPDX-License-Identifier: MIT
|
||||||
|
# *
|
||||||
|
# * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
# * this software and associated documentation files (the "Software"), to deal in
|
||||||
|
# * the Software without restriction, including without limitation the rights to
|
||||||
|
# * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
# * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
# * subject to the following conditions:
|
||||||
|
# *
|
||||||
|
# * The above copyright notice and this permission notice shall be included in all
|
||||||
|
# * copies or substantial portions of the Software.
|
||||||
|
# *
|
||||||
|
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
# * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
# * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
# * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
# *
|
||||||
|
# * https://www.FreeRTOS.org
|
||||||
|
# * https://github.com/FreeRTOS
|
||||||
|
# *
|
||||||
|
# */
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
_THIS_FILE_DIRECTORY_ = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
_FREERTOS_PORTABLE_DIRECTORY_ = os.path.dirname(_THIS_FILE_DIRECTORY_)
|
||||||
|
|
||||||
|
_COMPILERS_ = ['GCC', 'IAR']
|
||||||
|
_ARCH_NS_ = ['ARM_CM85', 'ARM_CM85_NTZ', 'ARM_CM55', 'ARM_CM55_NTZ', 'ARM_CM52', 'ARM_CM52_NTZ', 'ARM_CM35P', 'ARM_CM35P_NTZ', 'ARM_CM33', 'ARM_CM33_NTZ', 'ARM_CM23', 'ARM_CM23_NTZ', 'ARM_STAR_MC3', 'ARM_STAR_MC3_NTZ']
|
||||||
|
_ARCH_S_ = ['ARM_CM85', 'ARM_CM55', 'ARM_CM52', 'ARM_CM35P', 'ARM_CM33', 'ARM_CM23', 'ARM_STAR_MC3']
|
||||||
|
|
||||||
|
# Files to be compiled in the Secure Project
|
||||||
|
_SECURE_COMMON_FILE_PATHS_ = [
|
||||||
|
os.path.join('secure', 'context'),
|
||||||
|
os.path.join('secure', 'heap'),
|
||||||
|
os.path.join('secure', 'init'),
|
||||||
|
os.path.join('secure', 'macros')
|
||||||
|
]
|
||||||
|
|
||||||
|
_SECURE_PORTABLE_FILE_PATHS_ = {
|
||||||
|
'GCC':{
|
||||||
|
'ARM_CM23' :[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM23')],
|
||||||
|
'ARM_CM33' :[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')],
|
||||||
|
'ARM_CM35P' :[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')],
|
||||||
|
'ARM_CM52' :[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')],
|
||||||
|
'ARM_CM55' :[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')],
|
||||||
|
'ARM_CM85' :[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')],
|
||||||
|
'ARM_STAR_MC3' :[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')]
|
||||||
|
},
|
||||||
|
'IAR':{
|
||||||
|
'ARM_CM23' :[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM23')],
|
||||||
|
'ARM_CM33' :[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')],
|
||||||
|
'ARM_CM35P' :[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')],
|
||||||
|
'ARM_CM52' :[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')],
|
||||||
|
'ARM_CM55' :[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')],
|
||||||
|
'ARM_CM85' :[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')],
|
||||||
|
'ARM_STAR_MC3' :[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Files to be compiled in the Non-Secure Project
|
||||||
|
_NONSECURE_COMMON_FILE_PATHS_ = [
|
||||||
|
'non_secure'
|
||||||
|
]
|
||||||
|
|
||||||
|
_NONSECURE_PORTABLE_FILE_PATHS_ = {
|
||||||
|
'GCC':{
|
||||||
|
'ARM_CM23' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM23')],
|
||||||
|
'ARM_CM23_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM23_NTZ')],
|
||||||
|
'ARM_CM33' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33')],
|
||||||
|
'ARM_CM33_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ')],
|
||||||
|
'ARM_CM35P' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'portasm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'mpu_wrappers_v2_asm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM35P', 'portmacro.h')],
|
||||||
|
'ARM_CM35P_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'portasm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'mpu_wrappers_v2_asm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM35P', 'portmacro.h')],
|
||||||
|
'ARM_CM52' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'portasm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'mpu_wrappers_v2_asm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM52', 'portmacro.h')],
|
||||||
|
'ARM_CM52_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'portasm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'mpu_wrappers_v2_asm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM52', 'portmacro.h')],
|
||||||
|
'ARM_CM55' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'portasm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'mpu_wrappers_v2_asm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM55', 'portmacro.h')],
|
||||||
|
'ARM_CM55_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'portasm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'mpu_wrappers_v2_asm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM55', 'portmacro.h')],
|
||||||
|
'ARM_CM85' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'portasm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'mpu_wrappers_v2_asm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM85', 'portmacro.h')],
|
||||||
|
'ARM_CM85_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'portasm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'mpu_wrappers_v2_asm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM85', 'portmacro.h')],
|
||||||
|
'ARM_STAR_MC3' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'portasm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'mpu_wrappers_v2_asm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_STAR_MC3', 'portmacro.h')],
|
||||||
|
'ARM_STAR_MC3_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'portasm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'mpu_wrappers_v2_asm.c'),
|
||||||
|
os.path.join('non_secure', 'portable', 'GCC', 'ARM_STAR_MC3', 'portmacro.h')]
|
||||||
|
},
|
||||||
|
'IAR':{
|
||||||
|
'ARM_CM23' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM23')],
|
||||||
|
'ARM_CM23_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM23_NTZ')],
|
||||||
|
'ARM_CM33' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33')],
|
||||||
|
'ARM_CM33_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ')],
|
||||||
|
'ARM_CM35P' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'portasm.s'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'mpu_wrappers_v2_asm.S'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM35P', 'portmacro.h')],
|
||||||
|
'ARM_CM35P_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'portasm.s'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'mpu_wrappers_v2_asm.S'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM35P', 'portmacro.h')],
|
||||||
|
'ARM_CM52' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'portasm.s'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'mpu_wrappers_v2_asm.S'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM52', 'portmacro.h')],
|
||||||
|
'ARM_CM52_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'portasm.s'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'mpu_wrappers_v2_asm.S'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM52', 'portmacro.h')],
|
||||||
|
'ARM_CM55' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'portasm.s'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'mpu_wrappers_v2_asm.S'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM55', 'portmacro.h')],
|
||||||
|
'ARM_CM55_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'portasm.s'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'mpu_wrappers_v2_asm.S'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM55', 'portmacro.h')],
|
||||||
|
'ARM_CM85' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'portasm.s'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'mpu_wrappers_v2_asm.S'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM85', 'portmacro.h')],
|
||||||
|
'ARM_CM85_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'portasm.s'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'mpu_wrappers_v2_asm.S'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM85', 'portmacro.h')],
|
||||||
|
'ARM_STAR_MC3' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'portasm.s'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'mpu_wrappers_v2_asm.S'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_STAR_MC3', 'portmacro.h')],
|
||||||
|
'ARM_STAR_MC3_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'portasm.s'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'mpu_wrappers_v2_asm.S'),
|
||||||
|
os.path.join('non_secure', 'portable', 'IAR', 'ARM_STAR_MC3', 'portmacro.h')]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def copy_files_in_dir(src_abs_path, dst_abs_path):
|
||||||
|
if os.path.isfile(src_abs_path):
|
||||||
|
print('Src: {}'.format(src_abs_path))
|
||||||
|
print('Dst: {}\n'.format(dst_abs_path))
|
||||||
|
shutil.copy2(src_abs_path, dst_abs_path)
|
||||||
|
else:
|
||||||
|
for src_file in os.listdir(src_abs_path):
|
||||||
|
src_file_abs_path = os.path.join(src_abs_path, src_file)
|
||||||
|
if os.path.isfile(src_file_abs_path) and src_file != 'ReadMe.txt':
|
||||||
|
if not os.path.exists(dst_abs_path):
|
||||||
|
os.makedirs(dst_abs_path)
|
||||||
|
print('Src: {}'.format(src_file_abs_path))
|
||||||
|
print('Dst: {}\n'.format(dst_abs_path))
|
||||||
|
shutil.copy2(src_file_abs_path, dst_abs_path)
|
||||||
|
|
||||||
|
|
||||||
|
def copy_common_files_for_compiler_and_arch(compiler, arch, src_paths, dst_path):
|
||||||
|
for src_path in src_paths:
|
||||||
|
|
||||||
|
src_abs_path = os.path.join(_THIS_FILE_DIRECTORY_, src_path)
|
||||||
|
dst_abs_path = os.path.join(_FREERTOS_PORTABLE_DIRECTORY_, compiler, arch, dst_path)
|
||||||
|
|
||||||
|
copy_files_in_dir(src_abs_path, dst_abs_path)
|
||||||
|
|
||||||
|
|
||||||
|
def copy_portable_files_for_compiler_and_arch(compiler, arch, src_paths, dst_path):
|
||||||
|
for src_path in src_paths[compiler][arch]:
|
||||||
|
|
||||||
|
src_abs_path = os.path.join(_THIS_FILE_DIRECTORY_, src_path)
|
||||||
|
dst_abs_path = os.path.join(_FREERTOS_PORTABLE_DIRECTORY_, compiler, arch, dst_path)
|
||||||
|
|
||||||
|
copy_files_in_dir(src_abs_path, dst_abs_path)
|
||||||
|
|
||||||
|
|
||||||
|
def copy_files():
|
||||||
|
# Copy Secure Files
|
||||||
|
for compiler in _COMPILERS_:
|
||||||
|
for arch in _ARCH_S_:
|
||||||
|
copy_common_files_for_compiler_and_arch(compiler, arch, _SECURE_COMMON_FILE_PATHS_, 'secure')
|
||||||
|
copy_portable_files_for_compiler_and_arch(compiler, arch, _SECURE_PORTABLE_FILE_PATHS_, 'secure')
|
||||||
|
|
||||||
|
# Copy Non-Secure Files
|
||||||
|
for compiler in _COMPILERS_:
|
||||||
|
for arch in _ARCH_NS_:
|
||||||
|
copy_common_files_for_compiler_and_arch(compiler, arch, _NONSECURE_COMMON_FILE_PATHS_, 'non_secure')
|
||||||
|
copy_portable_files_for_compiler_and_arch(compiler, arch, _NONSECURE_PORTABLE_FILE_PATHS_, 'non_secure')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
copy_files()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
This directory tree contains the master copy of the FreeRTOS Armv8-M and
|
||||||
|
Armv8.1-M ports.
|
||||||
|
Do not use the files located here! These file are copied into separate
|
||||||
|
FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3]_NNN directories
|
||||||
|
prior to each FreeRTOS release.
|
||||||
|
|
||||||
|
If your Armv8-M/Armv8.1-M application uses TrustZone then use the files from the
|
||||||
|
FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3] directories.
|
||||||
|
|
||||||
|
If your Armv8-M/Armv8.1-M application does not use TrustZone then use the files from
|
||||||
|
the FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3]_NTZ directories.
|
||||||
File diff suppressed because it is too large
Load Diff
+2125
File diff suppressed because it is too large
Load Diff
+604
@@ -0,0 +1,604 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||||
|
* is defined correctly and privileged functions are placed in correct sections. */
|
||||||
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/* Portasm includes. */
|
||||||
|
#include "portasm.h"
|
||||||
|
|
||||||
|
/* System call numbers includes. */
|
||||||
|
#include "mpu_syscall_numbers.h"
|
||||||
|
|
||||||
|
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||||
|
* header files. */
|
||||||
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
#if ( configENABLE_FPU == 1 )
|
||||||
|
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" program_mpu_first_task: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r3] \n" /* r0 = pxCurrentTCB.*/
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" movs r3, #1 \n" /* r3 = 1. */
|
||||||
|
" bics r2, r3 \n" /* r2 = r2 & ~r3 i.e. Clear the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
" str r1, [r2] \n" /* Program MAIR0. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
" \n"
|
||||||
|
" movs r3, #4 \n" /* r3 = 4. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 4. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read first set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write first set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #5 \n" /* r3 = 5. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 5. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read second set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write second set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #6 \n" /* r3 = 6. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 6. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read third set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write third set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #7 \n" /* r3 = 6. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 7. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read fourth set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write fourth set of RBAR/RLAR registers. */
|
||||||
|
" \n"
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" movs r3, #1 \n" /* r3 = 1. */
|
||||||
|
" orrs r2, r3 \n" /* r2 = r2 | r3 i.e. Set the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
|
" restore_context_first_task: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* r1 = pxCurrentTCB.*/
|
||||||
|
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
|
||||||
|
" \n"
|
||||||
|
" restore_special_regs_first_task: \n"
|
||||||
|
" subs r2, #20 \n"
|
||||||
|
" ldmia r2!, {r0, r3-r6} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, r6 = LR. */
|
||||||
|
" subs r2, #20 \n"
|
||||||
|
" msr psp, r3 \n"
|
||||||
|
" msr control, r5 \n"
|
||||||
|
" mov lr, r6 \n"
|
||||||
|
" ldr r4, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
" str r0, [r4] \n" /* Restore xSecureContext. */
|
||||||
|
" \n"
|
||||||
|
" restore_general_regs_first_task: \n"
|
||||||
|
" subs r2, #32 \n"
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */
|
||||||
|
" stmia r3!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */
|
||||||
|
" stmia r3!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */
|
||||||
|
" subs r2, #48 \n"
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* Restore r8-r11. */
|
||||||
|
" mov r8, r4 \n" /* r8 = r4. */
|
||||||
|
" mov r9, r5 \n" /* r9 = r5. */
|
||||||
|
" mov r10, r6 \n" /* r10 = r6. */
|
||||||
|
" mov r11, r7 \n" /* r11 = r7. */
|
||||||
|
" subs r2, #32 \n"
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* Restore r4-r7. */
|
||||||
|
" subs r2, #16 \n"
|
||||||
|
" \n"
|
||||||
|
" restore_context_done_first_task: \n"
|
||||||
|
" str r2, [r1] \n" /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
" bx lr \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
|
||||||
|
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
" \n"
|
||||||
|
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||||
|
" ldr r4, =xSecureContext \n"
|
||||||
|
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */
|
||||||
|
" movs r1, #2 \n" /* r1 = 2. */
|
||||||
|
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */
|
||||||
|
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||||
|
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||||
|
" isb \n"
|
||||||
|
" bx r3 \n" /* Finally, branch to EXC_RETURN. */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||||
|
" movs r1, #1 \n" /* r1 = 1. */
|
||||||
|
" tst r0, r1 \n" /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||||
|
" beq running_privileged \n" /* If the result of previous AND operation was 0, branch. */
|
||||||
|
" movs r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
" running_privileged: \n"
|
||||||
|
" movs r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::: "r0", "r1", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* Read the CONTROL register. */
|
||||||
|
" movs r1, #1 \n" /* r1 = 1. */
|
||||||
|
" bics r0, r1 \n" /* Clear the bit 0. */
|
||||||
|
" msr control, r0 \n" /* Write back the new CONTROL value. */
|
||||||
|
" bx lr \n" /* Return to the caller. */
|
||||||
|
::: "r0", "r1", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||||
|
" movs r1, #1 \n" /* r1 = 1. */
|
||||||
|
" orrs r0, r1 \n" /* r0 = r0 | r1. */
|
||||||
|
" msr control, r0 \n" /* CONTROL = r0. */
|
||||||
|
" bx lr \n" /* Return to the caller. */
|
||||||
|
::: "r0", "r1", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r0, =0xe000ed08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||||
|
" ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */
|
||||||
|
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */
|
||||||
|
" msr msp, r0 \n" /* Set the MSP back to the start of the stack. */
|
||||||
|
" cpsie i \n" /* Globally enable interrupts. */
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" svc %0 \n" /* System call to start the first task. */
|
||||||
|
" nop \n"
|
||||||
|
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, PRIMASK \n"
|
||||||
|
" cpsid i \n"
|
||||||
|
" bx lr \n"
|
||||||
|
::: "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" msr PRIMASK, r0 \n"
|
||||||
|
" bx lr \n"
|
||||||
|
::: "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" .extern SecureContext_SaveContext \n"
|
||||||
|
" .extern SecureContext_LoadContext \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
" ldr r0, [r3] \n" /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later.*/
|
||||||
|
" ldr r2, [r1] \n" /* r2 = Location in TCB where the context should be saved. */
|
||||||
|
" \n"
|
||||||
|
" cbz r0, save_ns_context \n" /* No secure context to save. */
|
||||||
|
" save_s_context: \n"
|
||||||
|
" push {r0-r2, lr} \n"
|
||||||
|
" bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
" pop {r0-r3} \n" /* LR is now in r3. */
|
||||||
|
" mov lr, r3 \n" /* Restore LR. */
|
||||||
|
" \n"
|
||||||
|
" save_ns_context: \n"
|
||||||
|
" mov r3, lr \n" /* r3 = LR (EXC_RETURN). */
|
||||||
|
" lsls r3, r3, #25 \n" /* r3 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
" bmi save_special_regs \n" /* r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||||
|
" \n"
|
||||||
|
" save_general_regs: \n"
|
||||||
|
" mrs r3, psp \n"
|
||||||
|
" stmia r2!, {r4-r7} \n" /* Store r4-r7. */
|
||||||
|
" mov r4, r8 \n" /* r4 = r8. */
|
||||||
|
" mov r5, r9 \n" /* r5 = r9. */
|
||||||
|
" mov r6, r10 \n" /* r6 = r10. */
|
||||||
|
" mov r7, r11 \n" /* r7 = r11. */
|
||||||
|
" stmia r2!, {r4-r7} \n" /* Store r8-r11. */
|
||||||
|
" ldmia r3!, {r4-r7} \n" /* Copy half of the hardware saved context into r4-r7. */
|
||||||
|
" stmia r2!, {r4-r7} \n" /* Store the hardware saved context. */
|
||||||
|
" ldmia r3!, {r4-r7} \n" /* Copy rest half of the hardware saved context into r4-r7. */
|
||||||
|
" stmia r2!, {r4-r7} \n" /* Store the hardware saved context. */
|
||||||
|
" \n"
|
||||||
|
" save_special_regs: \n"
|
||||||
|
" mrs r3, psp \n" /* r3 = PSP. */
|
||||||
|
" movs r4, #0 \n" /* r4 = 0. 0 is stored in the PSPLIM slot. */
|
||||||
|
" mrs r5, control \n" /* r5 = CONTROL. */
|
||||||
|
" mov r6, lr \n" /* r6 = LR. */
|
||||||
|
" stmia r2!, {r0, r3-r6} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
|
||||||
|
" str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */
|
||||||
|
" \n"
|
||||||
|
" select_next_task: \n"
|
||||||
|
" cpsid i \n"
|
||||||
|
" bl vTaskSwitchContext \n"
|
||||||
|
" cpsie i \n"
|
||||||
|
" \n"
|
||||||
|
" program_mpu: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r3] \n" /* r0 = pxCurrentTCB.*/
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" movs r3, #1 \n" /* r3 = 1. */
|
||||||
|
" bics r2, r3 \n" /* r2 = r2 & ~r3 i.e. Clear the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
" str r1, [r2] \n" /* Program MAIR0. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
" \n"
|
||||||
|
" movs r3, #4 \n" /* r3 = 4. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 4. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read first set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write first set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #5 \n" /* r3 = 5. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 5. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read second set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write second set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #6 \n" /* r3 = 6. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 6. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read third set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write third set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #7 \n" /* r3 = 6. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 7. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read fourth set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write fourth set of RBAR/RLAR registers. */
|
||||||
|
" \n"
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" movs r3, #1 \n" /* r3 = 1. */
|
||||||
|
" orrs r2, r3 \n" /* r2 = r2 | r3 i.e. Set the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
|
" restore_context: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* r1 = pxCurrentTCB.*/
|
||||||
|
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
|
||||||
|
" \n"
|
||||||
|
" restore_special_regs: \n"
|
||||||
|
" subs r2, #20 \n"
|
||||||
|
" ldmia r2!, {r0, r3-r6} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, r6 = LR. */
|
||||||
|
" subs r2, #20 \n"
|
||||||
|
" msr psp, r3 \n"
|
||||||
|
" msr control, r5 \n"
|
||||||
|
" mov lr, r6 \n"
|
||||||
|
" ldr r4, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
" str r0, [r4] \n" /* Restore xSecureContext. */
|
||||||
|
" cbz r0, restore_ns_context \n" /* No secure context to restore. */
|
||||||
|
" \n"
|
||||||
|
" restore_s_context: \n"
|
||||||
|
" push {r1-r3, lr} \n"
|
||||||
|
" bl SecureContext_LoadContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
" pop {r1-r4} \n" /* LR is now in r4. */
|
||||||
|
" mov lr, r4 \n"
|
||||||
|
" \n"
|
||||||
|
" restore_ns_context: \n"
|
||||||
|
" mov r0, lr \n" /* r0 = LR (EXC_RETURN). */
|
||||||
|
" lsls r0, r0, #25 \n" /* r0 = r0 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
" bmi restore_context_done \n" /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||||
|
" \n"
|
||||||
|
" restore_general_regs: \n"
|
||||||
|
" subs r2, #32 \n"
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */
|
||||||
|
" stmia r3!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */
|
||||||
|
" stmia r3!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */
|
||||||
|
" subs r2, #48 \n"
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* Restore r8-r11. */
|
||||||
|
" mov r8, r4 \n" /* r8 = r4. */
|
||||||
|
" mov r9, r5 \n" /* r9 = r5. */
|
||||||
|
" mov r10, r6 \n" /* r10 = r6. */
|
||||||
|
" mov r11, r7 \n" /* r11 = r7. */
|
||||||
|
" subs r2, #32 \n"
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* Restore r4-r7. */
|
||||||
|
" subs r2, #16 \n"
|
||||||
|
" \n"
|
||||||
|
" restore_context_done: \n"
|
||||||
|
" str r2, [r1] \n" /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
" bx lr \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" .extern SecureContext_SaveContext \n"
|
||||||
|
" .extern SecureContext_LoadContext \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
" ldr r0, [r3] \n" /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later.*/
|
||||||
|
" mrs r2, psp \n" /* Read PSP in r2. */
|
||||||
|
" \n"
|
||||||
|
" cbz r0, save_ns_context \n" /* No secure context to save. */
|
||||||
|
" push {r0-r2, r14} \n"
|
||||||
|
" bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
" pop {r0-r3} \n" /* LR is now in r3. */
|
||||||
|
" mov lr, r3 \n" /* LR = r3. */
|
||||||
|
" lsls r1, r3, #25 \n" /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
" bpl save_ns_context \n" /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */
|
||||||
|
" subs r2, r2, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||||
|
" str r2, [r1] \n" /* Save the new top of stack in TCB. */
|
||||||
|
" movs r1, #0 \n" /* r1 = 0. 0 is stored in the PSPLIM slot. */
|
||||||
|
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||||
|
" stmia r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||||
|
" b select_next_task \n"
|
||||||
|
" \n"
|
||||||
|
" save_ns_context: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */
|
||||||
|
" subs r2, r2, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||||
|
" str r2, [r1] \n" /* Save the new top of stack in TCB. */
|
||||||
|
" movs r1, #0 \n" /* r1 = 0. 0 is stored in the PSPLIM slot. */
|
||||||
|
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||||
|
" stmia r2!, {r0, r1, r3-r7} \n" /* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
|
||||||
|
" mov r4, r8 \n" /* r4 = r8. */
|
||||||
|
" mov r5, r9 \n" /* r5 = r9. */
|
||||||
|
" mov r6, r10 \n" /* r6 = r10. */
|
||||||
|
" mov r7, r11 \n" /* r7 = r11. */
|
||||||
|
" stmia r2!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */
|
||||||
|
" \n"
|
||||||
|
" select_next_task: \n"
|
||||||
|
" cpsid i \n"
|
||||||
|
" bl vTaskSwitchContext \n"
|
||||||
|
" cpsie i \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */
|
||||||
|
" ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||||
|
" \n"
|
||||||
|
" ldmia r2!, {r0, r1, r4} \n" /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||||
|
" mov lr, r4 \n" /* LR = r4. */
|
||||||
|
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
" str r0, [r3] \n" /* Restore the task's xSecureContext. */
|
||||||
|
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */
|
||||||
|
" push {r2, r4} \n"
|
||||||
|
" bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
" pop {r2, r4} \n"
|
||||||
|
" mov lr, r4 \n" /* LR = r4. */
|
||||||
|
" lsls r1, r4, #25 \n" /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
" bpl restore_ns_context \n" /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||||
|
" msr psp, r2 \n" /* Remember the new top of stack for the task. */
|
||||||
|
" bx lr \n"
|
||||||
|
" \n"
|
||||||
|
" restore_ns_context: \n"
|
||||||
|
" adds r2, r2, #16 \n" /* Move to the high registers. */
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */
|
||||||
|
" mov r8, r4 \n" /* r8 = r4. */
|
||||||
|
" mov r9, r5 \n" /* r9 = r5. */
|
||||||
|
" mov r10, r6 \n" /* r10 = r6. */
|
||||||
|
" mov r11, r7 \n" /* r11 = r7. */
|
||||||
|
" msr psp, r2 \n" /* Remember the new top of stack for the task. */
|
||||||
|
" subs r2, r2, #32 \n" /* Go back to the low registers. */
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* Restore the low registers that are not automatically restored. */
|
||||||
|
" bx lr \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
|
||||||
|
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
".syntax unified \n"
|
||||||
|
".extern vPortSVCHandler_C \n"
|
||||||
|
".extern vSystemCallEnter \n"
|
||||||
|
".extern vSystemCallExit \n"
|
||||||
|
" \n"
|
||||||
|
"movs r0, #4 \n"
|
||||||
|
"mov r1, lr \n"
|
||||||
|
"tst r0, r1 \n"
|
||||||
|
"beq stack_on_msp \n"
|
||||||
|
"stack_on_psp: \n"
|
||||||
|
" mrs r0, psp \n"
|
||||||
|
" b route_svc \n"
|
||||||
|
"stack_on_msp: \n"
|
||||||
|
" mrs r0, msp \n"
|
||||||
|
" b route_svc \n"
|
||||||
|
" \n"
|
||||||
|
"route_svc: \n"
|
||||||
|
" ldr r3, [r0, #24] \n"
|
||||||
|
" subs r3, #2 \n"
|
||||||
|
" ldrb r2, [r3, #0] \n"
|
||||||
|
" cmp r2, %0 \n"
|
||||||
|
" blt system_call_enter \n"
|
||||||
|
" cmp r2, %1 \n"
|
||||||
|
" beq system_call_exit \n"
|
||||||
|
" b vPortSVCHandler_C \n"
|
||||||
|
" \n"
|
||||||
|
"system_call_enter: \n"
|
||||||
|
" b vSystemCallEnter \n"
|
||||||
|
"system_call_exit: \n"
|
||||||
|
" b vSystemCallExit \n"
|
||||||
|
" \n"
|
||||||
|
: /* No outputs. */
|
||||||
|
: "i" ( NUM_SYSTEM_CALLS ), "i" ( portSVC_SYSTEM_CALL_EXIT )
|
||||||
|
: "r0", "r1", "r2", "r3", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" movs r0, #4 \n"
|
||||||
|
" mov r1, lr \n"
|
||||||
|
" tst r0, r1 \n"
|
||||||
|
" beq stacking_used_msp \n"
|
||||||
|
" mrs r0, psp \n"
|
||||||
|
" ldr r2, =vPortSVCHandler_C \n"
|
||||||
|
" bx r2 \n"
|
||||||
|
" stacking_used_msp: \n"
|
||||||
|
" mrs r0, msp \n"
|
||||||
|
" ldr r2, =vPortSVCHandler_C \n"
|
||||||
|
" bx r2 \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" svc %0 \n" /* Secure context is allocated in the supervisor call. */
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r2, [r0] \n" /* The first item in the TCB is the top of the stack. */
|
||||||
|
" ldr r1, [r2] \n" /* The first item on the stack is the task's xSecureContext. */
|
||||||
|
" cmp r1, #0 \n" /* Raise svc if task's xSecureContext is not NULL. */
|
||||||
|
" bne free_secure_context \n" /* Branch if r1 != 0. */
|
||||||
|
" bx lr \n" /* There is no secure context (xSecureContext is NULL). */
|
||||||
|
" free_secure_context: \n"
|
||||||
|
" svc %0 \n" /* Secure context is freed in the supervisor call. */
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M23"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 0
|
||||||
|
#define portARMV8M_MINOR_VERSION 0
|
||||||
|
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
#error 16 MPU regions are not yet supported for this port.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#define configENABLE_MVE 0
|
||||||
|
#elif ( configENABLE_MVE != 0 )
|
||||||
|
#error configENABLE_MVE must be left undefined, or defined to 0 for the Cortex-M23.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||||
|
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+2125
File diff suppressed because it is too large
Load Diff
+516
@@ -0,0 +1,516 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||||
|
* is defined correctly and privileged functions are placed in correct sections. */
|
||||||
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/* Portasm includes. */
|
||||||
|
#include "portasm.h"
|
||||||
|
|
||||||
|
/* System call numbers includes. */
|
||||||
|
#include "mpu_syscall_numbers.h"
|
||||||
|
|
||||||
|
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||||
|
* header files. */
|
||||||
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
#if ( configENABLE_FPU == 1 )
|
||||||
|
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" program_mpu_first_task: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r3] \n" /* r0 = pxCurrentTCB.*/
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" movs r3, #1 \n" /* r3 = 1. */
|
||||||
|
" bics r2, r3 \n" /* r2 = r2 & ~r3 i.e. Clear the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
" str r1, [r2] \n" /* Program MAIR0. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
" \n"
|
||||||
|
" movs r3, #4 \n" /* r3 = 4. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 4. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read first set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write first set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #5 \n" /* r3 = 5. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 5. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read second set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write second set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #6 \n" /* r3 = 6. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 6. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read third set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write third set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #7 \n" /* r3 = 6. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 7. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read fourth set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write fourth set of RBAR/RLAR registers. */
|
||||||
|
" \n"
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" movs r3, #1 \n" /* r3 = 1. */
|
||||||
|
" orrs r2, r3 \n" /* r2 = r2 | r3 i.e. Set the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
|
" restore_context_first_task: \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
|
||||||
|
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
|
||||||
|
" \n"
|
||||||
|
" restore_special_regs_first_task: \n"
|
||||||
|
" subs r1, #16 \n"
|
||||||
|
" ldmia r1!, {r2-r5} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, r5 = LR. */
|
||||||
|
" subs r1, #16 \n"
|
||||||
|
" msr psp, r2 \n"
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
" msr psplim, r3 \n"
|
||||||
|
#endif
|
||||||
|
" msr control, r4 \n"
|
||||||
|
" mov lr, r5 \n"
|
||||||
|
" \n"
|
||||||
|
" restore_general_regs_first_task: \n"
|
||||||
|
" subs r1, #32 \n"
|
||||||
|
" ldmia r1!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */
|
||||||
|
" stmia r2!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */
|
||||||
|
" ldmia r1!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */
|
||||||
|
" stmia r2!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */
|
||||||
|
" subs r1, #48 \n"
|
||||||
|
" ldmia r1!, {r4-r7} \n" /* Restore r8-r11. */
|
||||||
|
" mov r8, r4 \n" /* r8 = r4. */
|
||||||
|
" mov r9, r5 \n" /* r9 = r5. */
|
||||||
|
" mov r10, r6 \n" /* r10 = r6. */
|
||||||
|
" mov r11, r7 \n" /* r11 = r7. */
|
||||||
|
" subs r1, #32 \n"
|
||||||
|
" ldmia r1!, {r4-r7} \n" /* Restore r4-r7. */
|
||||||
|
" subs r1, #16 \n"
|
||||||
|
" \n"
|
||||||
|
" restore_context_done_first_task: \n"
|
||||||
|
" str r1, [r0] \n" /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
" bx lr \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||||
|
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
" \n"
|
||||||
|
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */
|
||||||
|
#endif
|
||||||
|
" movs r1, #2 \n" /* r1 = 2. */
|
||||||
|
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */
|
||||||
|
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||||
|
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||||
|
" isb \n"
|
||||||
|
" bx r2 \n" /* Finally, branch to EXC_RETURN. */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||||
|
" movs r1, #1 \n" /* r1 = 1. */
|
||||||
|
" tst r0, r1 \n" /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||||
|
" beq running_privileged \n" /* If the result of previous AND operation was 0, branch. */
|
||||||
|
" movs r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
" running_privileged: \n"
|
||||||
|
" movs r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::: "r0", "r1", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* Read the CONTROL register. */
|
||||||
|
" movs r1, #1 \n" /* r1 = 1. */
|
||||||
|
" bics r0, r1 \n" /* Clear the bit 0. */
|
||||||
|
" msr control, r0 \n" /* Write back the new CONTROL value. */
|
||||||
|
" bx lr \n" /* Return to the caller. */
|
||||||
|
::: "r0", "r1", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||||
|
" movs r1, #1 \n" /* r1 = 1. */
|
||||||
|
" orrs r0, r1 \n" /* r0 = r0 | r1. */
|
||||||
|
" msr control, r0 \n" /* CONTROL = r0. */
|
||||||
|
" bx lr \n" /* Return to the caller. */
|
||||||
|
::: "r0", "r1", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r0, =0xe000ed08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||||
|
" ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */
|
||||||
|
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */
|
||||||
|
" msr msp, r0 \n" /* Set the MSP back to the start of the stack. */
|
||||||
|
" cpsie i \n" /* Globally enable interrupts. */
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" svc %0 \n" /* System call to start the first task. */
|
||||||
|
" nop \n"
|
||||||
|
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, PRIMASK \n"
|
||||||
|
" cpsid i \n"
|
||||||
|
" bx lr \n"
|
||||||
|
::: "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" msr PRIMASK, r0 \n"
|
||||||
|
" bx lr \n"
|
||||||
|
::: "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB. */
|
||||||
|
" ldr r1, [r0] \n" /* r1 = Location in TCB where the context should be saved. */
|
||||||
|
" mrs r2, psp \n" /* r2 = PSP. */
|
||||||
|
" \n"
|
||||||
|
" save_general_regs: \n"
|
||||||
|
" stmia r1!, {r4-r7} \n" /* Store r4-r7. */
|
||||||
|
" mov r4, r8 \n" /* r4 = r8. */
|
||||||
|
" mov r5, r9 \n" /* r5 = r9. */
|
||||||
|
" mov r6, r10 \n" /* r6 = r10. */
|
||||||
|
" mov r7, r11 \n" /* r7 = r11. */
|
||||||
|
" stmia r1!, {r4-r7} \n" /* Store r8-r11. */
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* Copy half of the hardware saved context into r4-r7. */
|
||||||
|
" stmia r1!, {r4-r7} \n" /* Store the hardware saved context. */
|
||||||
|
" ldmia r2!, {r4-r7} \n" /* Copy rest half of the hardware saved context into r4-r7. */
|
||||||
|
" stmia r1!, {r4-r7} \n" /* Store the hardware saved context. */
|
||||||
|
" \n"
|
||||||
|
" save_special_regs: \n"
|
||||||
|
" mrs r2, psp \n" /* r2 = PSP. */
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
" mrs r3, psplim \n" /* r3 = PSPLIM. */
|
||||||
|
#else
|
||||||
|
" movs r3, #0 \n" /* r3 = 0. 0 is stored in the PSPLIM slot. */
|
||||||
|
#endif
|
||||||
|
" mrs r4, control \n" /* r4 = CONTROL. */
|
||||||
|
" mov r5, lr \n" /* r5 = LR. */
|
||||||
|
" stmia r1!, {r2-r5} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
|
||||||
|
" str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */
|
||||||
|
" \n"
|
||||||
|
" select_next_task: \n"
|
||||||
|
" cpsid i \n"
|
||||||
|
" bl vTaskSwitchContext \n"
|
||||||
|
" cpsie i \n"
|
||||||
|
" \n"
|
||||||
|
" program_mpu: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r3] \n" /* r0 = pxCurrentTCB.*/
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" movs r3, #1 \n" /* r3 = 1. */
|
||||||
|
" bics r2, r3 \n" /* r2 = r2 & ~r3 i.e. Clear the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
" str r1, [r2] \n" /* Program MAIR0. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
" \n"
|
||||||
|
" movs r3, #4 \n" /* r3 = 4. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 4. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read first set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write first set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #5 \n" /* r3 = 5. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 5. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read second set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write second set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #6 \n" /* r3 = 6. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 6. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read third set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write third set of RBAR/RLAR registers. */
|
||||||
|
" movs r3, #7 \n" /* r3 = 6. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 7. */
|
||||||
|
" ldmia r0!, {r4-r5} \n" /* Read fourth set of RBAR/RLAR registers from TCB. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" stmia r2!, {r4-r5} \n" /* Write fourth set of RBAR/RLAR registers. */
|
||||||
|
" \n"
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" movs r3, #1 \n" /* r3 = 1. */
|
||||||
|
" orrs r2, r3 \n" /* r2 = r2 | r3 i.e. Set the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
|
" restore_context: \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
|
||||||
|
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
|
||||||
|
" \n"
|
||||||
|
" restore_special_regs: \n"
|
||||||
|
" subs r1, #16 \n"
|
||||||
|
" ldmia r1!, {r2-r5} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, r5 = LR. */
|
||||||
|
" subs r1, #16 \n"
|
||||||
|
" msr psp, r2 \n"
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
" msr psplim, r3 \n"
|
||||||
|
#endif
|
||||||
|
" msr control, r4 \n"
|
||||||
|
" mov lr, r5 \n"
|
||||||
|
" \n"
|
||||||
|
" restore_general_regs: \n"
|
||||||
|
" subs r1, #32 \n"
|
||||||
|
" ldmia r1!, {r4-r7} \n" /* r4-r7 contain half of the hardware saved context. */
|
||||||
|
" stmia r2!, {r4-r7} \n" /* Copy half of the the hardware saved context on the task stack. */
|
||||||
|
" ldmia r1!, {r4-r7} \n" /* r4-r7 contain rest half of the hardware saved context. */
|
||||||
|
" stmia r2!, {r4-r7} \n" /* Copy rest half of the the hardware saved context on the task stack. */
|
||||||
|
" subs r1, #48 \n"
|
||||||
|
" ldmia r1!, {r4-r7} \n" /* Restore r8-r11. */
|
||||||
|
" mov r8, r4 \n" /* r8 = r4. */
|
||||||
|
" mov r9, r5 \n" /* r9 = r5. */
|
||||||
|
" mov r10, r6 \n" /* r10 = r6. */
|
||||||
|
" mov r11, r7 \n" /* r11 = r7. */
|
||||||
|
" subs r1, #32 \n"
|
||||||
|
" ldmia r1!, {r4-r7} \n" /* Restore r4-r7. */
|
||||||
|
" subs r1, #16 \n"
|
||||||
|
" \n"
|
||||||
|
" restore_context_done: \n"
|
||||||
|
" str r1, [r0] \n" /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
" bx lr \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, psp \n" /* Read PSP in r0. */
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||||
|
" subs r0, r0, #40 \n" /* Make space for PSPLIM, LR and the remaining registers on the stack. */
|
||||||
|
" str r0, [r1] \n" /* Save the new top of stack in TCB. */
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||||
|
#else
|
||||||
|
" movs r2, #0 \n" /* r2 = 0. 0 is stored in the PSPLIM slot. */
|
||||||
|
#endif
|
||||||
|
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||||
|
" stmia r0!, {r2-r7} \n" /* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
|
||||||
|
" mov r4, r8 \n" /* r4 = r8. */
|
||||||
|
" mov r5, r9 \n" /* r5 = r9. */
|
||||||
|
" mov r6, r10 \n" /* r6 = r10. */
|
||||||
|
" mov r7, r11 \n" /* r7 = r11. */
|
||||||
|
" stmia r0!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */
|
||||||
|
" \n"
|
||||||
|
" cpsid i \n"
|
||||||
|
" bl vTaskSwitchContext \n"
|
||||||
|
" cpsie i \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||||
|
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, r0, #24 \n" /* Move to the high registers. */
|
||||||
|
" ldmia r0!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */
|
||||||
|
" mov r8, r4 \n" /* r8 = r4. */
|
||||||
|
" mov r9, r5 \n" /* r9 = r5. */
|
||||||
|
" mov r10, r6 \n" /* r10 = r6. */
|
||||||
|
" mov r11, r7 \n" /* r11 = r7. */
|
||||||
|
" msr psp, r0 \n" /* Remember the new top of stack for the task. */
|
||||||
|
" subs r0, r0, #40 \n" /* Move to the starting of the saved context. */
|
||||||
|
" ldmia r0!, {r2-r7} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */
|
||||||
|
#endif
|
||||||
|
" bx r3 \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
|
||||||
|
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
".syntax unified \n"
|
||||||
|
".extern vPortSVCHandler_C \n"
|
||||||
|
".extern vSystemCallEnter \n"
|
||||||
|
".extern vSystemCallExit \n"
|
||||||
|
" \n"
|
||||||
|
"movs r0, #4 \n"
|
||||||
|
"mov r1, lr \n"
|
||||||
|
"tst r0, r1 \n"
|
||||||
|
"beq stack_on_msp \n"
|
||||||
|
"stack_on_psp: \n"
|
||||||
|
" mrs r0, psp \n"
|
||||||
|
" b route_svc \n"
|
||||||
|
"stack_on_msp: \n"
|
||||||
|
" mrs r0, msp \n"
|
||||||
|
" b route_svc \n"
|
||||||
|
" \n"
|
||||||
|
"route_svc: \n"
|
||||||
|
" ldr r3, [r0, #24] \n"
|
||||||
|
" subs r3, #2 \n"
|
||||||
|
" ldrb r2, [r3, #0] \n"
|
||||||
|
" cmp r2, %0 \n"
|
||||||
|
" blt system_call_enter \n"
|
||||||
|
" cmp r2, %1 \n"
|
||||||
|
" beq system_call_exit \n"
|
||||||
|
" b vPortSVCHandler_C \n"
|
||||||
|
" \n"
|
||||||
|
"system_call_enter: \n"
|
||||||
|
" b vSystemCallEnter \n"
|
||||||
|
"system_call_exit: \n"
|
||||||
|
" b vSystemCallExit \n"
|
||||||
|
" \n"
|
||||||
|
: /* No outputs. */
|
||||||
|
: "i" ( NUM_SYSTEM_CALLS ), "i" ( portSVC_SYSTEM_CALL_EXIT )
|
||||||
|
: "r0", "r1", "r2", "r3", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" movs r0, #4 \n"
|
||||||
|
" mov r1, lr \n"
|
||||||
|
" tst r0, r1 \n"
|
||||||
|
" beq stacking_used_msp \n"
|
||||||
|
" mrs r0, psp \n"
|
||||||
|
" ldr r2, =vPortSVCHandler_C \n"
|
||||||
|
" bx r2 \n"
|
||||||
|
" stacking_used_msp: \n"
|
||||||
|
" mrs r0, msp \n"
|
||||||
|
" ldr r2, =vPortSVCHandler_C \n"
|
||||||
|
" bx r2 \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M23"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 0
|
||||||
|
#define portARMV8M_MINOR_VERSION 0
|
||||||
|
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
#error 16 MPU regions are not yet supported for this port.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#define configENABLE_MVE 0
|
||||||
|
#elif ( configENABLE_MVE != 0 )
|
||||||
|
#error configENABLE_MVE must be left undefined, or defined to 0 for the Cortex-M23.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||||
|
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+2056
File diff suppressed because it is too large
Load Diff
+621
@@ -0,0 +1,621 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
* Copyright 2024 Arm Limited and/or its affiliates
|
||||||
|
* <open-source-office@arm.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||||
|
* is defined correctly and privileged functions are placed in correct sections. */
|
||||||
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/* Portasm includes. */
|
||||||
|
#include "portasm.h"
|
||||||
|
|
||||||
|
/* System call numbers includes. */
|
||||||
|
#include "mpu_syscall_numbers.h"
|
||||||
|
|
||||||
|
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||||
|
* header files. */
|
||||||
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" program_mpu_first_task: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r3] \n" /* r0 = pxCurrentTCB. */
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" bic r2, #1 \n" /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
" str r1, [r2] \n" /* Program MAIR0. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" \n"
|
||||||
|
" movs r3, #4 \n" /* r3 = 4. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 4. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
" \n"
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
" movs r3, #8 \n" /* r3 = 8. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 8. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
" movs r3, #12 \n" /* r3 = 12. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 12. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||||
|
" \n"
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" orr r2, #1 \n" /* r2 = r1 | 1 i.e. Set the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
|
" restore_context_first_task: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* r1 = pxCurrentTCB.*/
|
||||||
|
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
|
||||||
|
" \n"
|
||||||
|
" restore_special_regs_first_task: \n"
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
|
||||||
|
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
" msr PAC_KEY_P_1, r4 \n"
|
||||||
|
" msr PAC_KEY_P_2, r5 \n"
|
||||||
|
" msr PAC_KEY_P_3, r6 \n"
|
||||||
|
" clrm {r3-r6} \n" /* Clear r3-r6. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
|
||||||
|
" msr psp, r3 \n"
|
||||||
|
" msr psplim, r4 \n"
|
||||||
|
" msr control, r5 \n"
|
||||||
|
" ldr r4, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
" str r0, [r4] \n" /* Restore xSecureContext. */
|
||||||
|
" \n"
|
||||||
|
" restore_general_regs_first_task: \n"
|
||||||
|
" ldmdb r2!, {r4-r11} \n" /* r4-r11 contain hardware saved context. */
|
||||||
|
" stmia r3!, {r4-r11} \n" /* Copy the hardware saved context on the task stack. */
|
||||||
|
" ldmdb r2!, {r4-r11} \n" /* r4-r11 restored. */
|
||||||
|
" \n"
|
||||||
|
" restore_context_done_first_task: \n"
|
||||||
|
" str r2, [r1] \n" /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
" mov r0, #0 \n"
|
||||||
|
" msr basepri, r0 \n" /* Ensure that interrupts are enabled when the first task starts. */
|
||||||
|
" bx lr \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
|
||||||
|
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
" \n"
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
|
||||||
|
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
" msr PAC_KEY_P_2, r2 \n"
|
||||||
|
" msr PAC_KEY_P_1, r3 \n"
|
||||||
|
" msr PAC_KEY_P_0, r4 \n"
|
||||||
|
" clrm {r1-r4} \n" /* Clear r1-r4. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" \n"
|
||||||
|
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||||
|
" ldr r4, =xSecureContext \n"
|
||||||
|
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */
|
||||||
|
" msr psplim, r2 \n" /* Set this task's PSPLIM value. */
|
||||||
|
" mrs r1, control \n" /* Obtain current control register value. */
|
||||||
|
" orrs r1, r1, #2 \n" /* r1 = r1 | 0x2 - Set the second bit to use the program stack pointer (PSP). */
|
||||||
|
" msr control, r1 \n" /* Write back the new control register value. */
|
||||||
|
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||||
|
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||||
|
" isb \n"
|
||||||
|
" mov r0, #0 \n"
|
||||||
|
" msr basepri, r0 \n" /* Ensure that interrupts are enabled when the first task starts. */
|
||||||
|
" bx r3 \n" /* Finally, branch to EXC_RETURN. */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||||
|
" tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||||
|
" ite ne \n"
|
||||||
|
" movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||||
|
" moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::: "r0", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* Read the CONTROL register. */
|
||||||
|
" bic r0, #1 \n" /* Clear the bit 0. */
|
||||||
|
" msr control, r0 \n" /* Write back the new CONTROL value. */
|
||||||
|
" bx lr \n" /* Return to the caller. */
|
||||||
|
::: "r0", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||||
|
" orr r0, #1 \n" /* r0 = r0 | 1. */
|
||||||
|
" msr control, r0 \n" /* CONTROL = r0. */
|
||||||
|
" bx lr \n" /* Return to the caller. */
|
||||||
|
::: "r0", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r0, =0xe000ed08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||||
|
" ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */
|
||||||
|
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */
|
||||||
|
" msr msp, r0 \n" /* Set the MSP back to the start of the stack. */
|
||||||
|
" cpsie i \n" /* Globally enable interrupts. */
|
||||||
|
" cpsie f \n"
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" svc %0 \n" /* System call to start the first task. */
|
||||||
|
" nop \n"
|
||||||
|
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, basepri \n" /* r0 = basepri. Return original basepri value. */
|
||||||
|
" mov r1, %0 \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
" msr basepri, r1 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" msr basepri, r0 \n" /* basepri = ulMask. */
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::: "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" .extern SecureContext_SaveContext \n"
|
||||||
|
" .extern SecureContext_LoadContext \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
" ldr r0, [r3] \n" /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||||
|
" ldr r2, [r1] \n" /* r2 = Location in TCB where the context should be saved. */
|
||||||
|
" \n"
|
||||||
|
" cbz r0, save_ns_context \n" /* No secure context to save. */
|
||||||
|
" save_s_context: \n"
|
||||||
|
" push {r0-r2, lr} \n"
|
||||||
|
" bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
" pop {r0-r2, lr} \n"
|
||||||
|
" \n"
|
||||||
|
" save_ns_context: \n"
|
||||||
|
" mov r3, lr \n" /* r3 = LR (EXC_RETURN). */
|
||||||
|
" lsls r3, r3, #25 \n" /* r3 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
" bmi save_special_regs \n" /* r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||||
|
" \n"
|
||||||
|
" save_general_regs: \n"
|
||||||
|
" mrs r3, psp \n"
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
" add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */
|
||||||
|
" tst lr, #0x10 \n"
|
||||||
|
" ittt eq \n"
|
||||||
|
" vstmiaeq r2!, {s16-s31} \n" /* Store s16-s31. */
|
||||||
|
" vldmiaeq r3, {s0-s16} \n" /* Copy hardware saved FP context into s0-s16. */
|
||||||
|
" vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */
|
||||||
|
" sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
" stmia r2!, {r4-r11} \n" /* Store r4-r11. */
|
||||||
|
" ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
|
||||||
|
" stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */
|
||||||
|
" \n"
|
||||||
|
" save_special_regs: \n"
|
||||||
|
" mrs r3, psp \n" /* r3 = PSP. */
|
||||||
|
" mrs r4, psplim \n" /* r4 = PSPLIM. */
|
||||||
|
" mrs r5, control \n" /* r5 = CONTROL. */
|
||||||
|
" stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" mrs r3, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
|
||||||
|
" mrs r4, PAC_KEY_P_1 \n"
|
||||||
|
" mrs r5, PAC_KEY_P_2 \n"
|
||||||
|
" mrs r6, PAC_KEY_P_3 \n"
|
||||||
|
" stmia r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the task's context. */
|
||||||
|
" clrm {r3-r6} \n" /* Clear r3-r6. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */
|
||||||
|
" \n"
|
||||||
|
" select_next_task: \n"
|
||||||
|
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||||
|
" msr basepri, r0 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" bl vTaskSwitchContext \n"
|
||||||
|
" mov r0, #0 \n" /* r0 = 0. */
|
||||||
|
" msr basepri, r0 \n" /* Enable interrupts. */
|
||||||
|
" \n"
|
||||||
|
" program_mpu: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r3] \n" /* r0 = pxCurrentTCB.*/
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" bic r2, #1 \n" /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
" str r1, [r2] \n" /* Program MAIR0. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" \n"
|
||||||
|
" movs r3, #4 \n" /* r3 = 4. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 4. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
" \n"
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
" movs r3, #8 \n" /* r3 = 8. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 8. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
" movs r3, #12 \n" /* r3 = 12. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 12. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||||
|
" \n"
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" orr r2, #1 \n" /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
|
" restore_context: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* r1 = pxCurrentTCB.*/
|
||||||
|
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
|
||||||
|
" \n"
|
||||||
|
" restore_special_regs: \n"
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
|
||||||
|
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
" msr PAC_KEY_P_1, r4 \n"
|
||||||
|
" msr PAC_KEY_P_2, r5 \n"
|
||||||
|
" msr PAC_KEY_P_3, r6 \n"
|
||||||
|
" clrm {r3-r6} \n" /* Clear r3-r6. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
|
||||||
|
" msr psp, r3 \n"
|
||||||
|
" msr psplim, r4 \n"
|
||||||
|
" msr control, r5 \n"
|
||||||
|
" ldr r4, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
" str r0, [r4] \n" /* Restore xSecureContext. */
|
||||||
|
" cbz r0, restore_ns_context \n" /* No secure context to restore. */
|
||||||
|
" \n"
|
||||||
|
" restore_s_context: \n"
|
||||||
|
" push {r1-r3, lr} \n"
|
||||||
|
" bl SecureContext_LoadContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
" pop {r1-r3, lr} \n"
|
||||||
|
" \n"
|
||||||
|
" restore_ns_context: \n"
|
||||||
|
" mov r0, lr \n" /* r0 = LR (EXC_RETURN). */
|
||||||
|
" lsls r0, r0, #25 \n" /* r0 = r0 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
" bmi restore_context_done \n" /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||||
|
" \n"
|
||||||
|
" restore_general_regs: \n"
|
||||||
|
" ldmdb r2!, {r4-r11} \n" /* r4-r11 contain hardware saved context. */
|
||||||
|
" stmia r3!, {r4-r11} \n" /* Copy the hardware saved context on the task stack. */
|
||||||
|
" ldmdb r2!, {r4-r11} \n" /* r4-r11 restored. */
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
" tst lr, #0x10 \n"
|
||||||
|
" ittt eq \n"
|
||||||
|
" vldmdbeq r2!, {s0-s16} \n" /* s0-s16 contain hardware saved FP context. */
|
||||||
|
" vstmiaeq r3!, {s0-s16} \n" /* Copy hardware saved FP context on the task stack. */
|
||||||
|
" vldmdbeq r2!, {s16-s31} \n" /* Restore s16-s31. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
" \n"
|
||||||
|
" restore_context_done: \n"
|
||||||
|
" str r2, [r1] \n" /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
" bx lr \n"
|
||||||
|
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" .extern SecureContext_SaveContext \n"
|
||||||
|
" .extern SecureContext_LoadContext \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
" ldr r0, [r3] \n" /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||||
|
" mrs r2, psp \n" /* Read PSP in r2. */
|
||||||
|
" \n"
|
||||||
|
" cbz r0, save_ns_context \n" /* No secure context to save. */
|
||||||
|
" save_s_context: \n"
|
||||||
|
" push {r0-r2, lr} \n"
|
||||||
|
" bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
" pop {r0-r2, lr} \n"
|
||||||
|
" \n"
|
||||||
|
" save_ns_context: \n"
|
||||||
|
" mov r3, lr \n" /* r3 = LR (EXC_RETURN). */
|
||||||
|
" lsls r3, r3, #25 \n" /* r3 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
" bmi save_special_regs \n" /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
|
||||||
|
" \n"
|
||||||
|
" save_general_regs: \n"
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||||
|
" it eq \n"
|
||||||
|
" vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
" stmdb r2!, {r4-r11} \n" /* Store the registers that are not saved automatically. */
|
||||||
|
" \n"
|
||||||
|
" save_special_regs: \n"
|
||||||
|
" mrs r3, psplim \n" /* r3 = PSPLIM. */
|
||||||
|
" stmdb r2!, {r0, r3, lr} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" mrs r3, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
|
||||||
|
" mrs r4, PAC_KEY_P_2 \n"
|
||||||
|
" mrs r5, PAC_KEY_P_1 \n"
|
||||||
|
" mrs r6, PAC_KEY_P_0 \n"
|
||||||
|
" stmdb r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the stack. */
|
||||||
|
" clrm {r3-r6} \n" /* Clear r3-r6. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" \n"
|
||||||
|
" str r2, [r1] \n" /* Save the new top of stack in TCB. */
|
||||||
|
" \n"
|
||||||
|
" select_next_task: \n"
|
||||||
|
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||||
|
" msr basepri, r0 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" bl vTaskSwitchContext \n"
|
||||||
|
" mov r0, #0 \n" /* r0 = 0. */
|
||||||
|
" msr basepri, r0 \n" /* Enable interrupts. */
|
||||||
|
" \n"
|
||||||
|
" restore_context: \n"
|
||||||
|
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */
|
||||||
|
" ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||||
|
" \n"
|
||||||
|
" restore_special_regs: \n"
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" ldmia r2!, {r3-r6} \n" /* Read task's dedicated PAC key from stack. */
|
||||||
|
" msr PAC_KEY_P_3, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
" msr PAC_KEY_P_2, r4 \n"
|
||||||
|
" msr PAC_KEY_P_1, r5 \n"
|
||||||
|
" msr PAC_KEY_P_0, r6 \n"
|
||||||
|
" clrm {r3-r6} \n" /* Clear r3-r6. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" ldmia r2!, {r0, r3, lr} \n" /* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
|
||||||
|
" msr psplim, r3 \n" /* Restore the PSPLIM register value for the task. */
|
||||||
|
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
" str r0, [r3] \n" /* Restore the task's xSecureContext. */
|
||||||
|
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
|
||||||
|
" \n"
|
||||||
|
" restore_s_context: \n"
|
||||||
|
" push {r1-r3, lr} \n"
|
||||||
|
" bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
" pop {r1-r3, lr} \n"
|
||||||
|
" \n"
|
||||||
|
" restore_ns_context: \n"
|
||||||
|
" mov r0, lr \n" /* r0 = LR (EXC_RETURN). */
|
||||||
|
" lsls r0, r0, #25 \n" /* r0 = r0 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
" bmi restore_context_done \n" /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||||
|
" \n"
|
||||||
|
" restore_general_regs: \n"
|
||||||
|
" ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||||
|
" it eq \n"
|
||||||
|
" vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
" \n"
|
||||||
|
" restore_context_done: \n"
|
||||||
|
" msr psp, r2 \n" /* Remember the new top of stack for the task. */
|
||||||
|
" bx lr \n"
|
||||||
|
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
|
||||||
|
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
".syntax unified \n"
|
||||||
|
".extern vPortSVCHandler_C \n"
|
||||||
|
".extern vSystemCallEnter \n"
|
||||||
|
".extern vSystemCallExit \n"
|
||||||
|
" \n"
|
||||||
|
"tst lr, #4 \n"
|
||||||
|
"ite eq \n"
|
||||||
|
"mrseq r0, msp \n"
|
||||||
|
"mrsne r0, psp \n"
|
||||||
|
" \n"
|
||||||
|
"ldr r1, [r0, #24] \n"
|
||||||
|
"ldrb r2, [r1, #-2] \n"
|
||||||
|
"cmp r2, %0 \n"
|
||||||
|
"blt syscall_enter \n"
|
||||||
|
"cmp r2, %1 \n"
|
||||||
|
"beq syscall_exit \n"
|
||||||
|
"b vPortSVCHandler_C \n"
|
||||||
|
" \n"
|
||||||
|
"syscall_enter: \n"
|
||||||
|
" mov r1, lr \n"
|
||||||
|
" b vSystemCallEnter \n"
|
||||||
|
" \n"
|
||||||
|
"syscall_exit: \n"
|
||||||
|
" mov r1, lr \n"
|
||||||
|
" b vSystemCallExit \n"
|
||||||
|
" \n"
|
||||||
|
: /* No outputs. */
|
||||||
|
: "i" ( NUM_SYSTEM_CALLS ), "i" ( portSVC_SYSTEM_CALL_EXIT )
|
||||||
|
: "r0", "r1", "r2", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" tst lr, #4 \n"
|
||||||
|
" ite eq \n"
|
||||||
|
" mrseq r0, msp \n"
|
||||||
|
" mrsne r0, psp \n"
|
||||||
|
" ldr r1, =vPortSVCHandler_C \n"
|
||||||
|
" bx r1 \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" svc %0 \n" /* Secure context is allocated in the supervisor call. */
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r2, [r0] \n" /* The first item in the TCB is the top of the stack. */
|
||||||
|
" ldr r1, [r2] \n" /* The first item on the stack is the task's xSecureContext. */
|
||||||
|
" cmp r1, #0 \n" /* Raise svc if task's xSecureContext is not NULL. */
|
||||||
|
" it ne \n"
|
||||||
|
" svcne %0 \n" /* Secure context is freed in the supervisor call. */
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
+81
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M33"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 0
|
||||||
|
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#define configENABLE_MVE 0
|
||||||
|
#elif ( configENABLE_MVE != 0 )
|
||||||
|
#error configENABLE_MVE must be left undefined, or defined to 0 for the Cortex-M33.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+2055
File diff suppressed because it is too large
Load Diff
+524
@@ -0,0 +1,524 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
* Copyright 2024 Arm Limited and/or its affiliates
|
||||||
|
* <open-source-office@arm.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||||
|
* is defined correctly and privileged functions are placed in correct sections. */
|
||||||
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/* Portasm includes. */
|
||||||
|
#include "portasm.h"
|
||||||
|
|
||||||
|
/* System call numbers includes. */
|
||||||
|
#include "mpu_syscall_numbers.h"
|
||||||
|
|
||||||
|
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||||
|
* header files. */
|
||||||
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" program_mpu_first_task: \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB. */
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" bic r2, #1 \n" /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
" str r1, [r2] \n" /* Program MAIR0. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" \n"
|
||||||
|
" movs r3, #4 \n" /* r3 = 4. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 4. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
" \n"
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
" movs r3, #8 \n" /* r3 = 8. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 8. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
" movs r3, #12 \n" /* r3 = 12. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 12. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||||
|
" \n"
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" orr r2, #1 \n" /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
|
" restore_context_first_task: \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
|
||||||
|
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
|
||||||
|
" \n"
|
||||||
|
" restore_special_regs_first_task: \n"
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
|
||||||
|
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
" msr PAC_KEY_P_1, r3 \n"
|
||||||
|
" msr PAC_KEY_P_2, r4 \n"
|
||||||
|
" msr PAC_KEY_P_3, r5 \n"
|
||||||
|
" clrm {r2-r5} \n" /* Clear r2-r5. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
|
||||||
|
" msr psp, r2 \n"
|
||||||
|
" msr psplim, r3 \n"
|
||||||
|
" msr control, r4 \n"
|
||||||
|
" \n"
|
||||||
|
" restore_general_regs_first_task: \n"
|
||||||
|
" ldmdb r1!, {r4-r11} \n" /* r4-r11 contain hardware saved context. */
|
||||||
|
" stmia r2!, {r4-r11} \n" /* Copy the hardware saved context on the task stack. */
|
||||||
|
" ldmdb r1!, {r4-r11} \n" /* r4-r11 restored. */
|
||||||
|
" \n"
|
||||||
|
" restore_context_done_first_task: \n"
|
||||||
|
" str r1, [r0] \n" /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
" mov r0, #0 \n"
|
||||||
|
" msr basepri, r0 \n" /* Ensure that interrupts are enabled when the first task starts. */
|
||||||
|
" bx lr \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||||
|
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
" \n"
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
|
||||||
|
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
" msr PAC_KEY_P_2, r2 \n"
|
||||||
|
" msr PAC_KEY_P_1, r3 \n"
|
||||||
|
" msr PAC_KEY_P_0, r4 \n"
|
||||||
|
" clrm {r1-r4} \n" /* Clear r1-r4. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" \n"
|
||||||
|
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||||
|
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */
|
||||||
|
" mrs r1, control \n" /* Obtain current control register value. */
|
||||||
|
" orrs r1, r1, #2 \n" /* r1 = r1 | 0x2 - Set the second bit to use the program stack pointer (PSP). */
|
||||||
|
" msr control, r1 \n" /* Write back the new control register value. */
|
||||||
|
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||||
|
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||||
|
" isb \n"
|
||||||
|
" mov r0, #0 \n"
|
||||||
|
" msr basepri, r0 \n" /* Ensure that interrupts are enabled when the first task starts. */
|
||||||
|
" bx r2 \n" /* Finally, branch to EXC_RETURN. */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||||
|
" tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||||
|
" ite ne \n"
|
||||||
|
" movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||||
|
" moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::: "r0", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* Read the CONTROL register. */
|
||||||
|
" bic r0, #1 \n" /* Clear the bit 0. */
|
||||||
|
" msr control, r0 \n" /* Write back the new CONTROL value. */
|
||||||
|
" bx lr \n" /* Return to the caller. */
|
||||||
|
::: "r0", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||||
|
" orr r0, #1 \n" /* r0 = r0 | 1. */
|
||||||
|
" msr control, r0 \n" /* CONTROL = r0. */
|
||||||
|
" bx lr \n" /* Return to the caller. */
|
||||||
|
::: "r0", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r0, =0xe000ed08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||||
|
" ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */
|
||||||
|
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */
|
||||||
|
" msr msp, r0 \n" /* Set the MSP back to the start of the stack. */
|
||||||
|
" cpsie i \n" /* Globally enable interrupts. */
|
||||||
|
" cpsie f \n"
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" svc %0 \n" /* System call to start the first task. */
|
||||||
|
" nop \n"
|
||||||
|
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, basepri \n" /* r0 = basepri. Return original basepri value. */
|
||||||
|
" mov r1, %0 \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
" msr basepri, r1 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" msr basepri, r0 \n" /* basepri = ulMask. */
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" bx lr \n" /* Return. */
|
||||||
|
::: "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB. */
|
||||||
|
" ldr r1, [r0] \n" /* r1 = Location in TCB where the context should be saved. */
|
||||||
|
" mrs r2, psp \n" /* r2 = PSP. */
|
||||||
|
" \n"
|
||||||
|
" save_general_regs: \n"
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
" add r2, r2, #0x20 \n" /* Move r2 to location where s0 is saved. */
|
||||||
|
" tst lr, #0x10 \n"
|
||||||
|
" ittt eq \n"
|
||||||
|
" vstmiaeq r1!, {s16-s31} \n" /* Store s16-s31. */
|
||||||
|
" vldmiaeq r2, {s0-s16} \n" /* Copy hardware saved FP context into s0-s16. */
|
||||||
|
" vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */
|
||||||
|
" sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
" stmia r1!, {r4-r11} \n" /* Store r4-r11. */
|
||||||
|
" ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
|
||||||
|
" stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */
|
||||||
|
" \n"
|
||||||
|
" save_special_regs: \n"
|
||||||
|
" mrs r3, psplim \n" /* r3 = PSPLIM. */
|
||||||
|
" mrs r4, control \n" /* r4 = CONTROL. */
|
||||||
|
" stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" mrs r2, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
|
||||||
|
" mrs r3, PAC_KEY_P_1 \n"
|
||||||
|
" mrs r4, PAC_KEY_P_2 \n"
|
||||||
|
" mrs r5, PAC_KEY_P_3 \n"
|
||||||
|
" stmia r1!, {r2-r5} \n" /* Store the task's dedicated PAC key on the task's context. */
|
||||||
|
" clrm {r2-r5} \n" /* Clear r2-r5. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */
|
||||||
|
" \n"
|
||||||
|
" select_next_task: \n"
|
||||||
|
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||||
|
" msr basepri, r0 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" bl vTaskSwitchContext \n"
|
||||||
|
" mov r0, #0 \n" /* r0 = 0. */
|
||||||
|
" msr basepri, r0 \n" /* Enable interrupts. */
|
||||||
|
" \n"
|
||||||
|
" program_mpu: \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB. */
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" bic r2, #1 \n" /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
" str r1, [r2] \n" /* Program MAIR0. */
|
||||||
|
" \n"
|
||||||
|
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
" \n"
|
||||||
|
" movs r3, #4 \n" /* r3 = 4. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 4. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
" \n"
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
" movs r3, #8 \n" /* r3 = 8. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 8. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
" movs r3, #12 \n" /* r3 = 12. */
|
||||||
|
" str r3, [r1] \n" /* Program RNR = 12. */
|
||||||
|
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||||
|
" \n"
|
||||||
|
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" orr r2, #1 \n" /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
|
||||||
|
" str r2, [r1] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
|
" restore_context: \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
|
||||||
|
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
|
||||||
|
" \n"
|
||||||
|
" restore_special_regs: \n"
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
|
||||||
|
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
" msr PAC_KEY_P_1, r3 \n"
|
||||||
|
" msr PAC_KEY_P_2, r4 \n"
|
||||||
|
" msr PAC_KEY_P_3, r5 \n"
|
||||||
|
" clrm {r2-r5} \n" /* Clear r2-r5. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
|
||||||
|
" msr psp, r2 \n"
|
||||||
|
" msr psplim, r3 \n"
|
||||||
|
" msr control, r4 \n"
|
||||||
|
" \n"
|
||||||
|
" restore_general_regs: \n"
|
||||||
|
" ldmdb r1!, {r4-r11} \n" /* r4-r11 contain hardware saved context. */
|
||||||
|
" stmia r2!, {r4-r11} \n" /* Copy the hardware saved context on the task stack. */
|
||||||
|
" ldmdb r1!, {r4-r11} \n" /* r4-r11 restored. */
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
" tst lr, #0x10 \n"
|
||||||
|
" ittt eq \n"
|
||||||
|
" vldmdbeq r1!, {s0-s16} \n" /* s0-s16 contain hardware saved FP context. */
|
||||||
|
" vstmiaeq r2!, {s0-s16} \n" /* Copy hardware saved FP context on the task stack. */
|
||||||
|
" vldmdbeq r1!, {s16-s31} \n" /* Restore s16-s31. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
" \n"
|
||||||
|
" restore_context_done: \n"
|
||||||
|
" str r1, [r0] \n" /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
" bx lr \n"
|
||||||
|
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r0, psp \n" /* Read PSP in r0. */
|
||||||
|
" \n"
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||||
|
" it eq \n"
|
||||||
|
" vstmdbeq r0!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
" \n"
|
||||||
|
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||||
|
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||||
|
" stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
|
||||||
|
" \n"
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" mrs r1, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
|
||||||
|
" mrs r2, PAC_KEY_P_2 \n"
|
||||||
|
" mrs r3, PAC_KEY_P_1 \n"
|
||||||
|
" mrs r4, PAC_KEY_P_0 \n"
|
||||||
|
" stmdb r0!, {r1-r4} \n" /* Store the task's dedicated PAC key on the stack. */
|
||||||
|
" clrm {r1-r4} \n" /* Clear r1-r4. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||||
|
" str r0, [r1] \n" /* Save the new top of stack in TCB. */
|
||||||
|
" \n"
|
||||||
|
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||||
|
" msr basepri, r0 \n" /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" bl vTaskSwitchContext \n"
|
||||||
|
" mov r0, #0 \n" /* r0 = 0. */
|
||||||
|
" msr basepri, r0 \n" /* Enable interrupts. */
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||||
|
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||||
|
" \n"
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
" ldmia r0!, {r2-r5} \n" /* Read task's dedicated PAC key from stack. */
|
||||||
|
" msr PAC_KEY_P_3, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
" msr PAC_KEY_P_2, r3 \n"
|
||||||
|
" msr PAC_KEY_P_1, r4 \n"
|
||||||
|
" msr PAC_KEY_P_0, r5 \n"
|
||||||
|
" clrm {r2-r5} \n" /* Clear r2-r5. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
" \n"
|
||||||
|
" ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
|
||||||
|
" \n"
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
" tst r3, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||||
|
" it eq \n"
|
||||||
|
" vldmiaeq r0!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
" \n"
|
||||||
|
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */
|
||||||
|
" msr psp, r0 \n" /* Remember the new top of stack for the task. */
|
||||||
|
" bx r3 \n"
|
||||||
|
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
|
||||||
|
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
".syntax unified \n"
|
||||||
|
".extern vPortSVCHandler_C \n"
|
||||||
|
".extern vSystemCallEnter \n"
|
||||||
|
".extern vSystemCallExit \n"
|
||||||
|
" \n"
|
||||||
|
"tst lr, #4 \n"
|
||||||
|
"ite eq \n"
|
||||||
|
"mrseq r0, msp \n"
|
||||||
|
"mrsne r0, psp \n"
|
||||||
|
" \n"
|
||||||
|
"ldr r1, [r0, #24] \n"
|
||||||
|
"ldrb r2, [r1, #-2] \n"
|
||||||
|
"cmp r2, %0 \n"
|
||||||
|
"blt syscall_enter \n"
|
||||||
|
"cmp r2, %1 \n"
|
||||||
|
"beq syscall_exit \n"
|
||||||
|
"b vPortSVCHandler_C \n"
|
||||||
|
" \n"
|
||||||
|
"syscall_enter: \n"
|
||||||
|
" mov r1, lr \n"
|
||||||
|
" b vSystemCallEnter \n"
|
||||||
|
" \n"
|
||||||
|
"syscall_exit: \n"
|
||||||
|
" mov r1, lr \n"
|
||||||
|
" b vSystemCallExit \n"
|
||||||
|
" \n"
|
||||||
|
: /* No outputs. */
|
||||||
|
: "i" ( NUM_SYSTEM_CALLS ), "i" ( portSVC_SYSTEM_CALL_EXIT )
|
||||||
|
: "r0", "r1", "r2", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" tst lr, #4 \n"
|
||||||
|
" ite eq \n"
|
||||||
|
" mrseq r0, msp \n"
|
||||||
|
" mrsne r0, psp \n"
|
||||||
|
" ldr r1, =vPortSVCHandler_C \n"
|
||||||
|
" bx r1 \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
+81
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M33"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 0
|
||||||
|
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#define configENABLE_MVE 0
|
||||||
|
#elif ( configENABLE_MVE != 0 )
|
||||||
|
#error configENABLE_MVE must be left undefined, or defined to 0 for the Cortex-M33.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+81
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M35P"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 0
|
||||||
|
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#define configENABLE_MVE 0
|
||||||
|
#elif ( configENABLE_MVE != 0 )
|
||||||
|
#error configENABLE_MVE must be left undefined, or defined to 0 for the Cortex-M35.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
* Copyright (c) 2025 Arm Technology (China) Co., Ltd.All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#error configENABLE_MVE must be defined in FreeRTOSConfig.h. Set configENABLE_MVE to 1 to enable the MVE or 0 to disable the MVE.
|
||||||
|
#endif /* configENABLE_MVE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M52"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 1
|
||||||
|
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#error configENABLE_MVE must be defined in FreeRTOSConfig.h. Set configENABLE_MVE to 1 to enable the MVE or 0 to disable the MVE.
|
||||||
|
#endif /* configENABLE_MVE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M55"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 1
|
||||||
|
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#error configENABLE_MVE must be defined in FreeRTOSConfig.h. Set configENABLE_MVE to 1 to enable the MVE or 0 to disable the MVE.
|
||||||
|
#endif /* configENABLE_MVE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M85"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 1
|
||||||
|
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
* Copyright (c) 2026 Arm Technology (China) Co., Ltd.All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#error configENABLE_MVE must be defined in FreeRTOSConfig.h. Set configENABLE_MVE to 1 to enable the MVE or 0 to disable the MVE.
|
||||||
|
#endif /* configENABLE_MVE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "STAR-MC3"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 1
|
||||||
|
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+1312
File diff suppressed because it is too large
Load Diff
+525
@@ -0,0 +1,525 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||||
|
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||||
|
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||||
|
the code is included in C files but excluded by the preprocessor in assembly
|
||||||
|
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||||
|
#include "FreeRTOSConfig.h"
|
||||||
|
|
||||||
|
/* System call numbers includes. */
|
||||||
|
#include "mpu_syscall_numbers.h"
|
||||||
|
|
||||||
|
#ifndef configUSE_MPU_WRAPPERS_V1
|
||||||
|
#define configUSE_MPU_WRAPPERS_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
EXTERN pxCurrentTCB
|
||||||
|
EXTERN xSecureContext
|
||||||
|
EXTERN vTaskSwitchContext
|
||||||
|
EXTERN vPortSVCHandler_C
|
||||||
|
EXTERN SecureContext_SaveContext
|
||||||
|
EXTERN SecureContext_LoadContext
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
EXTERN vSystemCallEnter
|
||||||
|
EXTERN vSystemCallExit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PUBLIC xIsPrivileged
|
||||||
|
PUBLIC vResetPrivilege
|
||||||
|
PUBLIC vPortAllocateSecureContext
|
||||||
|
PUBLIC vRestoreContextOfFirstTask
|
||||||
|
PUBLIC vRaisePrivilege
|
||||||
|
PUBLIC vStartFirstTask
|
||||||
|
PUBLIC ulSetInterruptMask
|
||||||
|
PUBLIC vClearInterruptMask
|
||||||
|
PUBLIC PendSV_Handler
|
||||||
|
PUBLIC SVC_Handler
|
||||||
|
PUBLIC vPortFreeSecureContext
|
||||||
|
|
||||||
|
#if ( configENABLE_FPU == 1 )
|
||||||
|
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*---------------- Unprivileged Functions -------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SECTION .text:CODE:NOROOT(2)
|
||||||
|
THUMB
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
xIsPrivileged:
|
||||||
|
mrs r0, control /* r0 = CONTROL. */
|
||||||
|
movs r1, #1 /* r1 = 1. */
|
||||||
|
tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||||
|
beq running_privileged /* If the result of previous AND operation was 0, branch. */
|
||||||
|
movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||||
|
bx lr /* Return. */
|
||||||
|
running_privileged:
|
||||||
|
movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||||
|
bx lr /* Return. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vResetPrivilege:
|
||||||
|
mrs r0, control /* r0 = CONTROL. */
|
||||||
|
movs r1, #1 /* r1 = 1. */
|
||||||
|
orrs r0, r1 /* r0 = r0 | r1. */
|
||||||
|
msr control, r0 /* CONTROL = r0. */
|
||||||
|
bx lr /* Return to the caller. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vPortAllocateSecureContext:
|
||||||
|
svc 100 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 100. */
|
||||||
|
bx lr /* Return. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*----------------- Privileged Functions --------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SECTION privileged_functions:CODE:NOROOT(2)
|
||||||
|
THUMB
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
vRestoreContextOfFirstTask:
|
||||||
|
program_mpu_first_task:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r3] /* r0 = pxCurrentTCB.*/
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
movs r3, #1 /* r3 = 1. */
|
||||||
|
bics r2, r3 /* r2 = r2 & ~r3 i.e. Clear the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Disable MPU. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
str r1, [r2] /* Program MAIR0. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
|
||||||
|
movs r3, #4 /* r3 = 4. */
|
||||||
|
str r3, [r1] /* Program RNR = 4. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read first set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write first set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #5 /* r3 = 5. */
|
||||||
|
str r3, [r1] /* Program RNR = 5. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read second set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write second set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #6 /* r3 = 6. */
|
||||||
|
str r3, [r1] /* Program RNR = 6. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read third set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write third set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #7 /* r3 = 6. */
|
||||||
|
str r3, [r1] /* Program RNR = 7. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read fourth set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write fourth set of RBAR/RLAR registers. */
|
||||||
|
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
movs r3, #1 /* r3 = 1. */
|
||||||
|
orrs r2, r3 /* r2 = r2 | r3 i.e. Set the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
|
restore_context_first_task:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* r1 = pxCurrentTCB.*/
|
||||||
|
ldr r2, [r1] /* r2 = Location of saved context in TCB. */
|
||||||
|
|
||||||
|
restore_special_regs_first_task:
|
||||||
|
subs r2, #20
|
||||||
|
ldmia r2!, {r0, r3-r6} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, r6 = LR. */
|
||||||
|
subs r2, #20
|
||||||
|
msr psp, r3
|
||||||
|
msr control, r5
|
||||||
|
mov lr, r6
|
||||||
|
ldr r4, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
str r0, [r4] /* Restore xSecureContext. */
|
||||||
|
|
||||||
|
restore_general_regs_first_task:
|
||||||
|
subs r2, #32
|
||||||
|
ldmia r2!, {r4-r7} /* r4-r7 contain half of the hardware saved context. */
|
||||||
|
stmia r3!, {r4-r7} /* Copy half of the the hardware saved context on the task stack. */
|
||||||
|
ldmia r2!, {r4-r7} /* r4-r7 contain rest half of the hardware saved context. */
|
||||||
|
stmia r3!, {r4-r7} /* Copy rest half of the the hardware saved context on the task stack. */
|
||||||
|
subs r2, #48
|
||||||
|
ldmia r2!, {r4-r7} /* Restore r8-r11. */
|
||||||
|
mov r8, r4 /* r8 = r4. */
|
||||||
|
mov r9, r5 /* r9 = r5. */
|
||||||
|
mov r10, r6 /* r10 = r6. */
|
||||||
|
mov r11, r7 /* r11 = r7. */
|
||||||
|
subs r2, #32
|
||||||
|
ldmia r2!, {r4-r7} /* Restore r4-r7. */
|
||||||
|
subs r2, #16
|
||||||
|
|
||||||
|
restore_context_done_first_task:
|
||||||
|
str r2, [r1] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
vRestoreContextOfFirstTask:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r3, [r2] /* Read pxCurrentTCB. */
|
||||||
|
ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
|
||||||
|
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||||
|
ldr r4, =xSecureContext
|
||||||
|
str r1, [r4] /* Set xSecureContext to this task's value for the same. */
|
||||||
|
movs r1, #2 /* r1 = 2. */
|
||||||
|
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||||
|
adds r0, #32 /* Discard everything up to r0. */
|
||||||
|
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||||
|
isb
|
||||||
|
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vRaisePrivilege:
|
||||||
|
mrs r0, control /* Read the CONTROL register. */
|
||||||
|
movs r1, #1 /* r1 = 1. */
|
||||||
|
bics r0, r1 /* Clear the bit 0. */
|
||||||
|
msr control, r0 /* Write back the new CONTROL value. */
|
||||||
|
bx lr /* Return to the caller. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vStartFirstTask:
|
||||||
|
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||||
|
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||||
|
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||||
|
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||||
|
cpsie i /* Globally enable interrupts. */
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
svc 102 /* System call to start the first task. portSVC_START_SCHEDULER = 102. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
ulSetInterruptMask:
|
||||||
|
mrs r0, PRIMASK
|
||||||
|
cpsid i
|
||||||
|
bx lr
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vClearInterruptMask:
|
||||||
|
msr PRIMASK, r0
|
||||||
|
bx lr
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
PendSV_Handler:
|
||||||
|
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later.*/
|
||||||
|
ldr r2, [r1] /* r2 = Location in TCB where the context should be saved. */
|
||||||
|
|
||||||
|
cbz r0, save_ns_context /* No secure context to save. */
|
||||||
|
save_s_context:
|
||||||
|
push {r0-r2, lr}
|
||||||
|
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
pop {r0-r3} /* LR is now in r3. */
|
||||||
|
mov lr, r3 /* Restore LR. */
|
||||||
|
|
||||||
|
save_ns_context:
|
||||||
|
mov r3, lr /* r3 = LR (EXC_RETURN). */
|
||||||
|
lsls r3, r3, #25 /* r3 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
bmi save_special_regs /* r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||||
|
|
||||||
|
save_general_regs:
|
||||||
|
mrs r3, psp
|
||||||
|
stmia r2!, {r4-r7} /* Store r4-r7. */
|
||||||
|
mov r4, r8 /* r4 = r8. */
|
||||||
|
mov r5, r9 /* r5 = r9. */
|
||||||
|
mov r6, r10 /* r6 = r10. */
|
||||||
|
mov r7, r11 /* r7 = r11. */
|
||||||
|
stmia r2!, {r4-r7} /* Store r8-r11. */
|
||||||
|
ldmia r3!, {r4-r7} /* Copy half of the hardware saved context into r4-r7. */
|
||||||
|
stmia r2!, {r4-r7} /* Store the hardware saved context. */
|
||||||
|
ldmia r3!, {r4-r7} /* Copy rest half of the hardware saved context into r4-r7. */
|
||||||
|
stmia r2!, {r4-r7} /* Store the hardware saved context. */
|
||||||
|
|
||||||
|
save_special_regs:
|
||||||
|
mrs r3, psp /* r3 = PSP. */
|
||||||
|
movs r4, #0 /* r4 = 0. 0 is stored in the PSPLIM slot. */
|
||||||
|
mrs r5, control /* r5 = CONTROL. */
|
||||||
|
mov r6, lr /* r6 = LR. */
|
||||||
|
stmia r2!, {r0, r3-r6} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
|
||||||
|
str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */
|
||||||
|
|
||||||
|
select_next_task:
|
||||||
|
cpsid i
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
cpsie i
|
||||||
|
|
||||||
|
program_mpu:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r3] /* r0 = pxCurrentTCB.*/
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
movs r3, #1 /* r3 = 1. */
|
||||||
|
bics r2, r3 /* r2 = r2 & ~r3 i.e. Clear the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Disable MPU. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
str r1, [r2] /* Program MAIR0. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
|
||||||
|
movs r3, #4 /* r3 = 4. */
|
||||||
|
str r3, [r1] /* Program RNR = 4. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read first set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write first set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #5 /* r3 = 5. */
|
||||||
|
str r3, [r1] /* Program RNR = 5. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read second set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write second set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #6 /* r3 = 6. */
|
||||||
|
str r3, [r1] /* Program RNR = 6. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read third set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write third set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #7 /* r3 = 6. */
|
||||||
|
str r3, [r1] /* Program RNR = 7. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read fourth set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write fourth set of RBAR/RLAR registers. */
|
||||||
|
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
movs r3, #1 /* r3 = 1. */
|
||||||
|
orrs r2, r3 /* r2 = r2 | r3 i.e. Set the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
|
restore_context:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* r1 = pxCurrentTCB.*/
|
||||||
|
ldr r2, [r1] /* r2 = Location of saved context in TCB. */
|
||||||
|
|
||||||
|
restore_special_regs:
|
||||||
|
subs r2, #20
|
||||||
|
ldmia r2!, {r0, r3-r6} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, r6 = LR. */
|
||||||
|
subs r2, #20
|
||||||
|
msr psp, r3
|
||||||
|
msr control, r5
|
||||||
|
mov lr, r6
|
||||||
|
ldr r4, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
str r0, [r4] /* Restore xSecureContext. */
|
||||||
|
cbz r0, restore_ns_context /* No secure context to restore. */
|
||||||
|
|
||||||
|
restore_s_context:
|
||||||
|
push {r1-r3, lr}
|
||||||
|
bl SecureContext_LoadContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
pop {r1-r4} /* LR is now in r4. */
|
||||||
|
mov lr, r4
|
||||||
|
|
||||||
|
restore_ns_context:
|
||||||
|
mov r0, lr /* r0 = LR (EXC_RETURN). */
|
||||||
|
lsls r0, r0, #25 /* r0 = r0 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
bmi restore_context_done /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||||
|
|
||||||
|
restore_general_regs:
|
||||||
|
subs r2, #32
|
||||||
|
ldmia r2!, {r4-r7} /* r4-r7 contain half of the hardware saved context. */
|
||||||
|
stmia r3!, {r4-r7} /* Copy half of the the hardware saved context on the task stack. */
|
||||||
|
ldmia r2!, {r4-r7} /* r4-r7 contain rest half of the hardware saved context. */
|
||||||
|
stmia r3!, {r4-r7} /* Copy rest half of the the hardware saved context on the task stack. */
|
||||||
|
subs r2, #48
|
||||||
|
ldmia r2!, {r4-r7} /* Restore r8-r11. */
|
||||||
|
mov r8, r4 /* r8 = r4. */
|
||||||
|
mov r9, r5 /* r9 = r5. */
|
||||||
|
mov r10, r6 /* r10 = r6. */
|
||||||
|
mov r11, r7 /* r11 = r7. */
|
||||||
|
subs r2, #32
|
||||||
|
ldmia r2!, {r4-r7} /* Restore r4-r7. */
|
||||||
|
subs r2, #16
|
||||||
|
|
||||||
|
restore_context_done:
|
||||||
|
str r2, [r1] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
PendSV_Handler:
|
||||||
|
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||||
|
mrs r2, psp /* Read PSP in r2. */
|
||||||
|
|
||||||
|
cbz r0, save_ns_context /* No secure context to save. */
|
||||||
|
push {r0-r2, r14}
|
||||||
|
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
pop {r0-r3} /* LR is now in r3. */
|
||||||
|
mov lr, r3 /* LR = r3. */
|
||||||
|
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||||
|
|
||||||
|
subs r2, r2, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||||
|
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||||
|
movs r1, #0 /* r1 = 0. 0 is stored in the PSPLIM slot. */
|
||||||
|
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||||
|
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||||
|
|
||||||
|
b select_next_task
|
||||||
|
|
||||||
|
save_ns_context:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||||
|
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||||
|
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||||
|
movs r1, #0 /* r1 = 0. 0 is stored in the PSPLIM slot. */
|
||||||
|
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||||
|
stmia r2!, {r0, r1, r3-r7} /* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
|
||||||
|
mov r4, r8 /* r4 = r8. */
|
||||||
|
mov r5, r9 /* r5 = r9. */
|
||||||
|
mov r6, r10 /* r6 = r10. */
|
||||||
|
mov r7, r11 /* r7 = r11. */
|
||||||
|
stmia r2!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||||
|
|
||||||
|
select_next_task:
|
||||||
|
cpsid i
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
cpsie i
|
||||||
|
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||||
|
ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||||
|
|
||||||
|
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||||
|
mov lr, r4 /* LR = r4. */
|
||||||
|
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
str r0, [r3] /* Restore the task's xSecureContext. */
|
||||||
|
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||||
|
push {r2, r4}
|
||||||
|
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
pop {r2, r4}
|
||||||
|
mov lr, r4 /* LR = r4. */
|
||||||
|
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||||
|
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
restore_ns_context:
|
||||||
|
adds r2, r2, #16 /* Move to the high registers. */
|
||||||
|
ldmia r2!, {r4-r7} /* Restore the high registers that are not automatically restored. */
|
||||||
|
mov r8, r4 /* r8 = r4. */
|
||||||
|
mov r9, r5 /* r9 = r5. */
|
||||||
|
mov r10, r6 /* r10 = r6. */
|
||||||
|
mov r11, r7 /* r11 = r7. */
|
||||||
|
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||||
|
subs r2, r2, #32 /* Go back to the low registers. */
|
||||||
|
ldmia r2!, {r4-r7} /* Restore the low registers that are not automatically restored. */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
|
||||||
|
SVC_Handler:
|
||||||
|
movs r0, #4
|
||||||
|
mov r1, lr
|
||||||
|
tst r0, r1
|
||||||
|
beq stack_on_msp
|
||||||
|
stack_on_psp:
|
||||||
|
mrs r0, psp
|
||||||
|
b route_svc
|
||||||
|
stack_on_msp:
|
||||||
|
mrs r0, msp
|
||||||
|
b route_svc
|
||||||
|
|
||||||
|
route_svc:
|
||||||
|
ldr r3, [r0, #24]
|
||||||
|
subs r3, #2
|
||||||
|
ldrb r2, [r3, #0]
|
||||||
|
cmp r2, #NUM_SYSTEM_CALLS
|
||||||
|
blt system_call_enter
|
||||||
|
cmp r2, #104 /* portSVC_SYSTEM_CALL_EXIT. */
|
||||||
|
beq system_call_exit
|
||||||
|
b vPortSVCHandler_C
|
||||||
|
|
||||||
|
system_call_enter:
|
||||||
|
b vSystemCallEnter
|
||||||
|
system_call_exit:
|
||||||
|
b vSystemCallExit
|
||||||
|
|
||||||
|
#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
SVC_Handler:
|
||||||
|
movs r0, #4
|
||||||
|
mov r1, lr
|
||||||
|
tst r0, r1
|
||||||
|
beq stacking_used_msp
|
||||||
|
mrs r0, psp
|
||||||
|
b vPortSVCHandler_C
|
||||||
|
stacking_used_msp:
|
||||||
|
mrs r0, msp
|
||||||
|
b vPortSVCHandler_C
|
||||||
|
|
||||||
|
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vPortFreeSecureContext:
|
||||||
|
ldr r2, [r0] /* The first item in the TCB is the top of the stack. */
|
||||||
|
ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */
|
||||||
|
cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */
|
||||||
|
bne free_secure_context /* Branch if r1 != 0. */
|
||||||
|
bx lr /* There is no secure context (xSecureContext is NULL). */
|
||||||
|
free_secure_context:
|
||||||
|
svc 101 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 101. */
|
||||||
|
bx lr /* Return. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
END
|
||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M23"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 0
|
||||||
|
#define portARMV8M_MINOR_VERSION 0
|
||||||
|
#define portDONT_DISCARD __root
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
#error 16 MPU regions are not yet supported for this port.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#define configENABLE_MVE 0
|
||||||
|
#elif ( configENABLE_MVE != 0 )
|
||||||
|
#error configENABLE_MVE must be left undefined, or defined to 0 for the Cortex-M23.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||||
|
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+1312
File diff suppressed because it is too large
Load Diff
+456
@@ -0,0 +1,456 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||||
|
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||||
|
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||||
|
the code is included in C files but excluded by the preprocessor in assembly
|
||||||
|
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||||
|
#include "FreeRTOSConfig.h"
|
||||||
|
|
||||||
|
/* System call numbers includes. */
|
||||||
|
#include "mpu_syscall_numbers.h"
|
||||||
|
|
||||||
|
#ifndef configUSE_MPU_WRAPPERS_V1
|
||||||
|
#define configUSE_MPU_WRAPPERS_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configRUN_FREERTOS_SECURE_ONLY
|
||||||
|
#define configRUN_FREERTOS_SECURE_ONLY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTERN pxCurrentTCB
|
||||||
|
EXTERN vTaskSwitchContext
|
||||||
|
EXTERN vPortSVCHandler_C
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
EXTERN vSystemCallEnter
|
||||||
|
EXTERN vSystemCallExit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PUBLIC xIsPrivileged
|
||||||
|
PUBLIC vResetPrivilege
|
||||||
|
PUBLIC vRestoreContextOfFirstTask
|
||||||
|
PUBLIC vRaisePrivilege
|
||||||
|
PUBLIC vStartFirstTask
|
||||||
|
PUBLIC ulSetInterruptMask
|
||||||
|
PUBLIC vClearInterruptMask
|
||||||
|
PUBLIC PendSV_Handler
|
||||||
|
PUBLIC SVC_Handler
|
||||||
|
|
||||||
|
#if ( configENABLE_FPU == 1 )
|
||||||
|
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*---------------- Unprivileged Functions -------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SECTION .text:CODE:NOROOT(2)
|
||||||
|
THUMB
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
xIsPrivileged:
|
||||||
|
mrs r0, control /* r0 = CONTROL. */
|
||||||
|
movs r1, #1 /* r1 = 1. */
|
||||||
|
tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||||
|
beq running_privileged /* If the result of previous AND operation was 0, branch. */
|
||||||
|
movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||||
|
bx lr /* Return. */
|
||||||
|
running_privileged:
|
||||||
|
movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||||
|
bx lr /* Return. */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vResetPrivilege:
|
||||||
|
mrs r0, control /* r0 = CONTROL. */
|
||||||
|
movs r1, #1 /* r1 = 1. */
|
||||||
|
orrs r0, r1 /* r0 = r0 | r1. */
|
||||||
|
msr control, r0 /* CONTROL = r0. */
|
||||||
|
bx lr /* Return to the caller. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*----------------- Privileged Functions --------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SECTION privileged_functions:CODE:NOROOT(2)
|
||||||
|
THUMB
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
vRestoreContextOfFirstTask:
|
||||||
|
program_mpu_first_task:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r3] /* r0 = pxCurrentTCB.*/
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
movs r3, #1 /* r3 = 1. */
|
||||||
|
bics r2, r3 /* r2 = r2 & ~r3 i.e. Clear the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Disable MPU. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
str r1, [r2] /* Program MAIR0. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
|
||||||
|
movs r3, #4 /* r3 = 4. */
|
||||||
|
str r3, [r1] /* Program RNR = 4. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read first set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write first set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #5 /* r3 = 5. */
|
||||||
|
str r3, [r1] /* Program RNR = 5. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read second set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write second set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #6 /* r3 = 6. */
|
||||||
|
str r3, [r1] /* Program RNR = 6. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read third set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write third set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #7 /* r3 = 6. */
|
||||||
|
str r3, [r1] /* Program RNR = 7. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read fourth set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write fourth set of RBAR/RLAR registers. */
|
||||||
|
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
movs r3, #1 /* r3 = 1. */
|
||||||
|
orrs r2, r3 /* r2 = r2 | r3 i.e. Set the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
|
restore_context_first_task:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r2] /* r0 = pxCurrentTCB.*/
|
||||||
|
ldr r1, [r0] /* r1 = Location of saved context in TCB. */
|
||||||
|
|
||||||
|
restore_special_regs_first_task:
|
||||||
|
subs r1, #16
|
||||||
|
ldmia r1!, {r2-r5} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, r5 = LR. */
|
||||||
|
subs r1, #16
|
||||||
|
msr psp, r2
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
msr psplim, r3
|
||||||
|
#endif
|
||||||
|
msr control, r4
|
||||||
|
mov lr, r5
|
||||||
|
|
||||||
|
restore_general_regs_first_task:
|
||||||
|
subs r1, #32
|
||||||
|
ldmia r1!, {r4-r7} /* r4-r7 contain half of the hardware saved context. */
|
||||||
|
stmia r2!, {r4-r7} /* Copy half of the the hardware saved context on the task stack. */
|
||||||
|
ldmia r1!, {r4-r7} /* r4-r7 contain rest half of the hardware saved context. */
|
||||||
|
stmia r2!, {r4-r7} /* Copy rest half of the the hardware saved context on the task stack. */
|
||||||
|
subs r1, #48
|
||||||
|
ldmia r1!, {r4-r7} /* Restore r8-r11. */
|
||||||
|
mov r8, r4 /* r8 = r4. */
|
||||||
|
mov r9, r5 /* r9 = r5. */
|
||||||
|
mov r10, r6 /* r10 = r6. */
|
||||||
|
mov r11, r7 /* r11 = r7. */
|
||||||
|
subs r1, #32
|
||||||
|
ldmia r1!, {r4-r7} /* Restore r4-r7. */
|
||||||
|
subs r1, #16
|
||||||
|
|
||||||
|
restore_context_done_first_task:
|
||||||
|
str r1, [r0] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
vRestoreContextOfFirstTask:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||||
|
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
|
||||||
|
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||||
|
#endif
|
||||||
|
movs r1, #2 /* r1 = 2. */
|
||||||
|
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||||
|
adds r0, #32 /* Discard everything up to r0. */
|
||||||
|
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||||
|
isb
|
||||||
|
bx r2 /* Finally, branch to EXC_RETURN. */
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vRaisePrivilege:
|
||||||
|
mrs r0, control /* Read the CONTROL register. */
|
||||||
|
movs r1, #1 /* r1 = 1. */
|
||||||
|
bics r0, r1 /* Clear the bit 0. */
|
||||||
|
msr control, r0 /* Write back the new CONTROL value. */
|
||||||
|
bx lr /* Return to the caller. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vStartFirstTask:
|
||||||
|
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||||
|
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||||
|
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||||
|
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||||
|
cpsie i /* Globally enable interrupts. */
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
svc 102 /* System call to start the first task. portSVC_START_SCHEDULER = 102. */
|
||||||
|
nop
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
ulSetInterruptMask:
|
||||||
|
mrs r0, PRIMASK
|
||||||
|
cpsid i
|
||||||
|
bx lr
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vClearInterruptMask:
|
||||||
|
msr PRIMASK, r0
|
||||||
|
bx lr
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
PendSV_Handler:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r2] /* r0 = pxCurrentTCB. */
|
||||||
|
ldr r1, [r0] /* r1 = Location in TCB where the context should be saved. */
|
||||||
|
mrs r2, psp /* r2 = PSP. */
|
||||||
|
|
||||||
|
save_general_regs:
|
||||||
|
stmia r1!, {r4-r7} /* Store r4-r7. */
|
||||||
|
mov r4, r8 /* r4 = r8. */
|
||||||
|
mov r5, r9 /* r5 = r9. */
|
||||||
|
mov r6, r10 /* r6 = r10. */
|
||||||
|
mov r7, r11 /* r7 = r11. */
|
||||||
|
stmia r1!, {r4-r7} /* Store r8-r11. */
|
||||||
|
ldmia r2!, {r4-r7} /* Copy half of the hardware saved context into r4-r7. */
|
||||||
|
stmia r1!, {r4-r7} /* Store the hardware saved context. */
|
||||||
|
ldmia r2!, {r4-r7} /* Copy rest half of the hardware saved context into r4-r7. */
|
||||||
|
stmia r1!, {r4-r7} /* Store the hardware saved context. */
|
||||||
|
|
||||||
|
save_special_regs:
|
||||||
|
mrs r2, psp /* r2 = PSP. */
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
mrs r3, psplim /* r3 = PSPLIM. */
|
||||||
|
#else
|
||||||
|
movs r3, #0 /* r3 = 0. 0 is stored in the PSPLIM slot. */
|
||||||
|
#endif
|
||||||
|
mrs r4, control /* r4 = CONTROL. */
|
||||||
|
mov r5, lr /* r5 = LR. */
|
||||||
|
stmia r1!, {r2-r5} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
|
||||||
|
str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */
|
||||||
|
|
||||||
|
select_next_task:
|
||||||
|
cpsid i
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
cpsie i
|
||||||
|
|
||||||
|
program_mpu:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r3] /* r0 = pxCurrentTCB.*/
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
movs r3, #1 /* r3 = 1. */
|
||||||
|
bics r2, r3 /* r2 = r2 & ~r3 i.e. Clear the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Disable MPU. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
str r1, [r2] /* Program MAIR0. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
|
||||||
|
movs r3, #4 /* r3 = 4. */
|
||||||
|
str r3, [r1] /* Program RNR = 4. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read first set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write first set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #5 /* r3 = 5. */
|
||||||
|
str r3, [r1] /* Program RNR = 5. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read second set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write second set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #6 /* r3 = 6. */
|
||||||
|
str r3, [r1] /* Program RNR = 6. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read third set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write third set of RBAR/RLAR registers. */
|
||||||
|
movs r3, #7 /* r3 = 6. */
|
||||||
|
str r3, [r1] /* Program RNR = 7. */
|
||||||
|
ldmia r0!, {r4-r5} /* Read fourth set of RBAR/RLAR registers from TCB. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
stmia r2!, {r4-r5} /* Write fourth set of RBAR/RLAR registers. */
|
||||||
|
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
movs r3, #1 /* r3 = 1. */
|
||||||
|
orrs r2, r3 /* r2 = r2 | r3 i.e. Set the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
|
restore_context:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r2] /* r0 = pxCurrentTCB.*/
|
||||||
|
ldr r1, [r0] /* r1 = Location of saved context in TCB. */
|
||||||
|
|
||||||
|
restore_special_regs:
|
||||||
|
subs r1, #16
|
||||||
|
ldmia r1!, {r2-r5} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, r5 = LR. */
|
||||||
|
subs r1, #16
|
||||||
|
msr psp, r2
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
msr psplim, r3
|
||||||
|
#endif
|
||||||
|
msr control, r4
|
||||||
|
mov lr, r5
|
||||||
|
|
||||||
|
restore_general_regs:
|
||||||
|
subs r1, #32
|
||||||
|
ldmia r1!, {r4-r7} /* r4-r7 contain half of the hardware saved context. */
|
||||||
|
stmia r2!, {r4-r7} /* Copy half of the the hardware saved context on the task stack. */
|
||||||
|
ldmia r1!, {r4-r7} /* r4-r7 contain rest half of the hardware saved context. */
|
||||||
|
stmia r2!, {r4-r7} /* Copy rest half of the the hardware saved context on the task stack. */
|
||||||
|
subs r1, #48
|
||||||
|
ldmia r1!, {r4-r7} /* Restore r8-r11. */
|
||||||
|
mov r8, r4 /* r8 = r4. */
|
||||||
|
mov r9, r5 /* r9 = r5. */
|
||||||
|
mov r10, r6 /* r10 = r6. */
|
||||||
|
mov r11, r7 /* r11 = r7. */
|
||||||
|
subs r1, #32
|
||||||
|
ldmia r1!, {r4-r7} /* Restore r4-r7. */
|
||||||
|
subs r1, #16
|
||||||
|
|
||||||
|
restore_context_done:
|
||||||
|
str r1, [r0] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
PendSV_Handler:
|
||||||
|
mrs r0, psp /* Read PSP in r0. */
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||||
|
|
||||||
|
subs r0, r0, #40 /* Make space for PSPLIM, LR and the remaining registers on the stack. */
|
||||||
|
str r0, [r1] /* Save the new top of stack in TCB. */
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
mrs r2, psplim /* r2 = PSPLIM. */
|
||||||
|
#else
|
||||||
|
movs r2, #0 /* r0 = 0. 0 is stored in the PSPLIM slot. */
|
||||||
|
#endif
|
||||||
|
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||||
|
stmia r0!, {r2-r7} /* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
|
||||||
|
mov r4, r8 /* r4 = r8. */
|
||||||
|
mov r5, r9 /* r5 = r9. */
|
||||||
|
mov r6, r10 /* r6 = r10. */
|
||||||
|
mov r7, r11 /* r7 = r11. */
|
||||||
|
stmia r0!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||||
|
|
||||||
|
cpsid i
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
cpsie i
|
||||||
|
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||||
|
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||||
|
|
||||||
|
adds r0, r0, #24 /* Move to the high registers. */
|
||||||
|
ldmia r0!, {r4-r7} /* Restore the high registers that are not automatically restored. */
|
||||||
|
mov r8, r4 /* r8 = r4. */
|
||||||
|
mov r9, r5 /* r9 = r5. */
|
||||||
|
mov r10, r6 /* r10 = r6. */
|
||||||
|
mov r11, r7 /* r11 = r7. */
|
||||||
|
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||||
|
subs r0, r0, #40 /* Move to the starting of the saved context. */
|
||||||
|
ldmia r0!, {r2-r7} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
|
||||||
|
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||||
|
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||||
|
#endif
|
||||||
|
bx r3
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
|
||||||
|
SVC_Handler:
|
||||||
|
movs r0, #4
|
||||||
|
mov r1, lr
|
||||||
|
tst r0, r1
|
||||||
|
beq stack_on_msp
|
||||||
|
stack_on_psp:
|
||||||
|
mrs r0, psp
|
||||||
|
b route_svc
|
||||||
|
stack_on_msp:
|
||||||
|
mrs r0, msp
|
||||||
|
b route_svc
|
||||||
|
|
||||||
|
route_svc:
|
||||||
|
ldr r3, [r0, #24]
|
||||||
|
subs r3, #2
|
||||||
|
ldrb r2, [r3, #0]
|
||||||
|
cmp r2, #NUM_SYSTEM_CALLS
|
||||||
|
blt system_call_enter
|
||||||
|
cmp r2, #104 /* portSVC_SYSTEM_CALL_EXIT. */
|
||||||
|
beq system_call_exit
|
||||||
|
b vPortSVCHandler_C
|
||||||
|
|
||||||
|
system_call_enter:
|
||||||
|
b vSystemCallEnter
|
||||||
|
system_call_exit:
|
||||||
|
b vSystemCallExit
|
||||||
|
|
||||||
|
#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
SVC_Handler:
|
||||||
|
movs r0, #4
|
||||||
|
mov r1, lr
|
||||||
|
tst r0, r1
|
||||||
|
beq stacking_used_msp
|
||||||
|
mrs r0, psp
|
||||||
|
b vPortSVCHandler_C
|
||||||
|
stacking_used_msp:
|
||||||
|
mrs r0, msp
|
||||||
|
b vPortSVCHandler_C
|
||||||
|
|
||||||
|
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
END
|
||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M23"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 0
|
||||||
|
#define portARMV8M_MINOR_VERSION 0
|
||||||
|
#define portDONT_DISCARD __root
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
#error 16 MPU regions are not yet supported for this port.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#define configENABLE_MVE 0
|
||||||
|
#elif ( configENABLE_MVE != 0 )
|
||||||
|
#error configENABLE_MVE must be left undefined, or defined to 0 for the Cortex-M23.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||||
|
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+1242
File diff suppressed because it is too large
Load Diff
+543
@@ -0,0 +1,543 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
* Copyright 2024 Arm Limited and/or its affiliates
|
||||||
|
* <open-source-office@arm.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||||
|
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||||
|
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||||
|
the code is included in C files but excluded by the preprocessor in assembly
|
||||||
|
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||||
|
#include "FreeRTOSConfig.h"
|
||||||
|
|
||||||
|
/* System call numbers includes. */
|
||||||
|
#include "mpu_syscall_numbers.h"
|
||||||
|
|
||||||
|
#ifndef configUSE_MPU_WRAPPERS_V1
|
||||||
|
#define configUSE_MPU_WRAPPERS_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTERN pxCurrentTCB
|
||||||
|
EXTERN xSecureContext
|
||||||
|
EXTERN vTaskSwitchContext
|
||||||
|
EXTERN vPortSVCHandler_C
|
||||||
|
EXTERN SecureContext_SaveContext
|
||||||
|
EXTERN SecureContext_LoadContext
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
EXTERN vSystemCallEnter
|
||||||
|
EXTERN vSystemCallExit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PUBLIC xIsPrivileged
|
||||||
|
PUBLIC vResetPrivilege
|
||||||
|
PUBLIC vPortAllocateSecureContext
|
||||||
|
PUBLIC vRestoreContextOfFirstTask
|
||||||
|
PUBLIC vRaisePrivilege
|
||||||
|
PUBLIC vStartFirstTask
|
||||||
|
PUBLIC ulSetInterruptMask
|
||||||
|
PUBLIC vClearInterruptMask
|
||||||
|
PUBLIC PendSV_Handler
|
||||||
|
PUBLIC SVC_Handler
|
||||||
|
PUBLIC vPortFreeSecureContext
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*---------------- Unprivileged Functions -------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SECTION .text:CODE:NOROOT(2)
|
||||||
|
THUMB
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
xIsPrivileged:
|
||||||
|
mrs r0, control /* r0 = CONTROL. */
|
||||||
|
tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||||
|
ite ne
|
||||||
|
movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||||
|
moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */
|
||||||
|
bx lr /* Return. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vResetPrivilege:
|
||||||
|
mrs r0, control /* r0 = CONTROL. */
|
||||||
|
orr r0, r0, #1 /* r0 = r0 | 1. */
|
||||||
|
msr control, r0 /* CONTROL = r0. */
|
||||||
|
bx lr /* Return to the caller. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vPortAllocateSecureContext:
|
||||||
|
svc 100 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 100. */
|
||||||
|
bx lr /* Return. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*----------------- Privileged Functions --------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SECTION privileged_functions:CODE:NOROOT(2)
|
||||||
|
THUMB
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
vRestoreContextOfFirstTask:
|
||||||
|
program_mpu_first_task:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r3] /* r0 = pxCurrentTCB. */
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
bic r2, #1 /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Disable MPU. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
str r1, [r2] /* Program MAIR0. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
|
||||||
|
movs r3, #4 /* r3 = 4. */
|
||||||
|
str r3, [r1] /* Program RNR = 4. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
movs r3, #8 /* r3 = 8. */
|
||||||
|
str r3, [r1] /* Program RNR = 8. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
movs r3, #12 /* r3 = 12. */
|
||||||
|
str r3, [r1] /* Program RNR = 12. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||||
|
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
orr r2, #1 /* r2 = r1 | 1 i.e. Set the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
|
restore_context_first_task:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* r1 = pxCurrentTCB.*/
|
||||||
|
ldr r2, [r1] /* r2 = Location of saved context in TCB. */
|
||||||
|
|
||||||
|
restore_special_regs_first_task:
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
|
||||||
|
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
msr PAC_KEY_P_1, r4
|
||||||
|
msr PAC_KEY_P_2, r5
|
||||||
|
msr PAC_KEY_P_3, r6
|
||||||
|
clrm {r3-r6} /* Clear r3-r6. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
|
||||||
|
msr psp, r3
|
||||||
|
msr psplim, r4
|
||||||
|
msr control, r5
|
||||||
|
ldr r4, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
str r0, [r4] /* Restore xSecureContext. */
|
||||||
|
|
||||||
|
restore_general_regs_first_task:
|
||||||
|
ldmdb r2!, {r4-r11} /* r4-r11 contain hardware saved context. */
|
||||||
|
stmia r3!, {r4-r11} /* Copy the hardware saved context on the task stack. */
|
||||||
|
ldmdb r2!, {r4-r11} /* r4-r11 restored. */
|
||||||
|
|
||||||
|
restore_context_done_first_task:
|
||||||
|
str r2, [r1] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
vRestoreContextOfFirstTask:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r3, [r2] /* Read pxCurrentTCB. */
|
||||||
|
ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
|
||||||
|
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
msr PAC_KEY_P_2, r2
|
||||||
|
msr PAC_KEY_P_1, r3
|
||||||
|
msr PAC_KEY_P_0, r4
|
||||||
|
clrm {r1-r4} /* Clear r1-r4. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
|
||||||
|
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||||
|
ldr r4, =xSecureContext
|
||||||
|
str r1, [r4] /* Set xSecureContext to this task's value for the same. */
|
||||||
|
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||||
|
mrs r1, control /* Obtain current control register value. */
|
||||||
|
orrs r1, r1, #2 /* r1 = r1 | 0x2 - Set the second bit to use the program stack pointe (PSP). */
|
||||||
|
msr control, r1 /* Write back the new control register value. */
|
||||||
|
adds r0, #32 /* Discard everything up to r0. */
|
||||||
|
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||||
|
isb
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||||
|
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vRaisePrivilege:
|
||||||
|
mrs r0, control /* Read the CONTROL register. */
|
||||||
|
bic r0, r0, #1 /* Clear the bit 0. */
|
||||||
|
msr control, r0 /* Write back the new CONTROL value. */
|
||||||
|
bx lr /* Return to the caller. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vStartFirstTask:
|
||||||
|
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||||
|
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||||
|
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||||
|
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||||
|
cpsie i /* Globally enable interrupts. */
|
||||||
|
cpsie f
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
svc 102 /* System call to start the first task. portSVC_START_SCHEDULER = 102. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
ulSetInterruptMask:
|
||||||
|
mrs r0, basepri /* r0 = basepri. Return original basepri value. */
|
||||||
|
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r1 /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
bx lr /* Return. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vClearInterruptMask:
|
||||||
|
msr basepri, r0 /* basepri = ulMask. */
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
bx lr /* Return. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
PendSV_Handler:
|
||||||
|
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||||
|
ldr r2, [r1] /* r2 = Location in TCB where the context should be saved. */
|
||||||
|
|
||||||
|
cbz r0, save_ns_context /* No secure context to save. */
|
||||||
|
save_s_context:
|
||||||
|
push {r0-r2, lr}
|
||||||
|
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
pop {r0-r2, lr}
|
||||||
|
|
||||||
|
save_ns_context:
|
||||||
|
mov r3, lr /* r3 = LR (EXC_RETURN). */
|
||||||
|
lsls r3, r3, #25 /* r3 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
bmi save_special_regs /* r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||||
|
|
||||||
|
save_general_regs:
|
||||||
|
mrs r3, psp
|
||||||
|
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
add r3, r3, #0x20 /* Move r3 to location where s0 is saved. */
|
||||||
|
tst lr, #0x10
|
||||||
|
ittt eq
|
||||||
|
vstmiaeq r2!, {s16-s31} /* Store s16-s31. */
|
||||||
|
vldmiaeq r3, {s0-s16} /* Copy hardware saved FP context into s0-s16. */
|
||||||
|
vstmiaeq r2!, {s0-s16} /* Store hardware saved FP context. */
|
||||||
|
sub r3, r3, #0x20 /* Set r3 back to the location of hardware saved context. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
|
||||||
|
stmia r2!, {r4-r11} /* Store r4-r11. */
|
||||||
|
ldmia r3, {r4-r11} /* Copy the hardware saved context into r4-r11. */
|
||||||
|
stmia r2!, {r4-r11} /* Store the hardware saved context. */
|
||||||
|
|
||||||
|
save_special_regs:
|
||||||
|
mrs r3, psp /* r3 = PSP. */
|
||||||
|
mrs r4, psplim /* r4 = PSPLIM. */
|
||||||
|
mrs r5, control /* r5 = CONTROL. */
|
||||||
|
stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
mrs r3, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
|
||||||
|
mrs r4, PAC_KEY_P_1
|
||||||
|
mrs r5, PAC_KEY_P_2
|
||||||
|
mrs r6, PAC_KEY_P_3
|
||||||
|
stmia r2!, {r3-r6} /* Store the task's dedicated PAC key on the task's context. */
|
||||||
|
clrm {r3-r6} /* Clear r3-r6. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
|
||||||
|
str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */
|
||||||
|
|
||||||
|
select_next_task:
|
||||||
|
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r0 /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
mov r0, #0 /* r0 = 0. */
|
||||||
|
msr basepri, r0 /* Enable interrupts. */
|
||||||
|
|
||||||
|
program_mpu:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r3] /* r0 = pxCurrentTCB.*/
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
bic r2, #1 /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Disable MPU. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
str r1, [r2] /* Program MAIR0. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
|
||||||
|
movs r3, #4 /* r3 = 4. */
|
||||||
|
str r3, [r1] /* Program RNR = 4. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
movs r3, #8 /* r3 = 8. */
|
||||||
|
str r3, [r1] /* Program RNR = 8. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
movs r3, #12 /* r3 = 12. */
|
||||||
|
str r3, [r1] /* Program RNR = 12. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||||
|
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
orr r2, #1 /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
|
restore_context:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* r1 = pxCurrentTCB.*/
|
||||||
|
ldr r2, [r1] /* r2 = Location of saved context in TCB. */
|
||||||
|
|
||||||
|
restore_special_regs:
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
|
||||||
|
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
msr PAC_KEY_P_1, r4
|
||||||
|
msr PAC_KEY_P_2, r5
|
||||||
|
msr PAC_KEY_P_3, r6
|
||||||
|
clrm {r3-r6} /* Clear r3-r6. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
|
||||||
|
msr psp, r3
|
||||||
|
msr psplim, r4
|
||||||
|
msr control, r5
|
||||||
|
ldr r4, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
str r0, [r4] /* Restore xSecureContext. */
|
||||||
|
cbz r0, restore_ns_context /* No secure context to restore. */
|
||||||
|
|
||||||
|
restore_s_context:
|
||||||
|
push {r1-r3, lr}
|
||||||
|
bl SecureContext_LoadContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
pop {r1-r3, lr}
|
||||||
|
|
||||||
|
restore_ns_context:
|
||||||
|
mov r0, lr /* r0 = LR (EXC_RETURN). */
|
||||||
|
lsls r0, r0, #25 /* r0 = r0 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
bmi restore_context_done /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||||
|
|
||||||
|
restore_general_regs:
|
||||||
|
ldmdb r2!, {r4-r11} /* r4-r11 contain hardware saved context. */
|
||||||
|
stmia r3!, {r4-r11} /* Copy the hardware saved context on the task stack. */
|
||||||
|
ldmdb r2!, {r4-r11} /* r4-r11 restored. */
|
||||||
|
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
tst lr, #0x10
|
||||||
|
ittt eq
|
||||||
|
vldmdbeq r2!, {s0-s16} /* s0-s16 contain hardware saved FP context. */
|
||||||
|
vstmiaeq r3!, {s0-s16} /* Copy hardware saved FP context on the task stack. */
|
||||||
|
vldmdbeq r2!, {s16-s31} /* Restore s16-s31. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
|
||||||
|
restore_context_done:
|
||||||
|
str r2, [r1] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
PendSV_Handler:
|
||||||
|
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||||
|
mrs r2, psp /* Read PSP in r2. */
|
||||||
|
|
||||||
|
cbz r0, save_ns_context /* No secure context to save. */
|
||||||
|
save_s_context:
|
||||||
|
push {r0-r2, lr}
|
||||||
|
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
pop {r0-r2, lr}
|
||||||
|
|
||||||
|
save_ns_context:
|
||||||
|
mov r3, lr /* r3 = LR. */
|
||||||
|
lsls r3, r3, #25 /* r3 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
bmi save_special_regs /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
|
||||||
|
|
||||||
|
save_general_regs:
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||||
|
it eq
|
||||||
|
vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
stmdb r2!, {r4-r11} /* Store the registers that are not saved automatically. */
|
||||||
|
|
||||||
|
save_special_regs:
|
||||||
|
mrs r3, psplim /* r3 = PSPLIM. */
|
||||||
|
stmdb r2!, {r0, r3, lr} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
mrs r3, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
|
||||||
|
mrs r4, PAC_KEY_P_2
|
||||||
|
mrs r5, PAC_KEY_P_1
|
||||||
|
mrs r6, PAC_KEY_P_0
|
||||||
|
stmdb r2!, {r3-r6} /* Store the task's dedicated PAC key on the stack. */
|
||||||
|
clrm {r3-r6} /* Clear r3-r6. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
|
||||||
|
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||||
|
|
||||||
|
select_next_task:
|
||||||
|
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r0 /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
mov r0, #0 /* r0 = 0. */
|
||||||
|
msr basepri, r0 /* Enable interrupts. */
|
||||||
|
|
||||||
|
restore_context:
|
||||||
|
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||||
|
ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||||
|
|
||||||
|
restore_special_regs:
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
ldmia r2!, {r3-r6} /* Read task's dedicated PAC key from stack. */
|
||||||
|
msr PAC_KEY_P_3, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
msr PAC_KEY_P_2, r4
|
||||||
|
msr PAC_KEY_P_1, r5
|
||||||
|
msr PAC_KEY_P_0, r6
|
||||||
|
clrm {r3-r6} /* Clear r3-r6. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
ldmia r2!, {r0, r3, lr} http://files.iar.com/ftp/pub/box/bxarm-9.60.3.deb/* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
|
||||||
|
msr psplim, r3 /* Restore the PSPLIM register value for the task. */
|
||||||
|
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||||
|
str r0, [r3] /* Restore the task's xSecureContext. */
|
||||||
|
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||||
|
|
||||||
|
restore_s_context:
|
||||||
|
push {r1-r3, lr}
|
||||||
|
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||||
|
pop {r1-r3, lr}
|
||||||
|
|
||||||
|
restore_ns_context:
|
||||||
|
mov r0, lr /* r0 = LR (EXC_RETURN). */
|
||||||
|
lsls r0, r0, #25 /* r0 = r0 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||||
|
bmi restore_context_done /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||||
|
|
||||||
|
restore_general_regs:
|
||||||
|
ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||||
|
it eq
|
||||||
|
vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
|
||||||
|
restore_context_done:
|
||||||
|
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
|
||||||
|
SVC_Handler:
|
||||||
|
tst lr, #4
|
||||||
|
ite eq
|
||||||
|
mrseq r0, msp
|
||||||
|
mrsne r0, psp
|
||||||
|
|
||||||
|
ldr r1, [r0, #24]
|
||||||
|
ldrb r2, [r1, #-2]
|
||||||
|
cmp r2, #NUM_SYSTEM_CALLS
|
||||||
|
blt syscall_enter
|
||||||
|
cmp r2, #104 /* portSVC_SYSTEM_CALL_EXIT. */
|
||||||
|
beq syscall_exit
|
||||||
|
b vPortSVCHandler_C
|
||||||
|
|
||||||
|
syscall_enter:
|
||||||
|
mov r1, lr
|
||||||
|
b vSystemCallEnter
|
||||||
|
|
||||||
|
syscall_exit:
|
||||||
|
mov r1, lr
|
||||||
|
b vSystemCallExit
|
||||||
|
|
||||||
|
#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
SVC_Handler:
|
||||||
|
tst lr, #4
|
||||||
|
ite eq
|
||||||
|
mrseq r0, msp
|
||||||
|
mrsne r0, psp
|
||||||
|
b vPortSVCHandler_C
|
||||||
|
|
||||||
|
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vPortFreeSecureContext:
|
||||||
|
/* r0 = uint32_t *pulTCB. */
|
||||||
|
ldr r2, [r0] /* The first item in the TCB is the top of the stack. */
|
||||||
|
ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */
|
||||||
|
cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */
|
||||||
|
it ne
|
||||||
|
svcne 101 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 101. */
|
||||||
|
bx lr /* Return. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
END
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M33"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 0
|
||||||
|
#define portDONT_DISCARD __root
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#define configENABLE_MVE 0
|
||||||
|
#elif ( configENABLE_MVE != 0 )
|
||||||
|
#error configENABLE_MVE must be left undefined, or defined to 0 for the Cortex-M33.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+1242
File diff suppressed because it is too large
Load Diff
+456
@@ -0,0 +1,456 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
* Copyright 2024 Arm Limited and/or its affiliates
|
||||||
|
* <open-source-office@arm.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||||
|
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||||
|
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||||
|
the code is included in C files but excluded by the preprocessor in assembly
|
||||||
|
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||||
|
#include "FreeRTOSConfig.h"
|
||||||
|
|
||||||
|
/* System call numbers includes. */
|
||||||
|
#include "mpu_syscall_numbers.h"
|
||||||
|
|
||||||
|
#ifndef configUSE_MPU_WRAPPERS_V1
|
||||||
|
#define configUSE_MPU_WRAPPERS_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTERN pxCurrentTCB
|
||||||
|
EXTERN vTaskSwitchContext
|
||||||
|
EXTERN vPortSVCHandler_C
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
EXTERN vSystemCallEnter
|
||||||
|
EXTERN vSystemCallExit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PUBLIC xIsPrivileged
|
||||||
|
PUBLIC vResetPrivilege
|
||||||
|
PUBLIC vRestoreContextOfFirstTask
|
||||||
|
PUBLIC vRaisePrivilege
|
||||||
|
PUBLIC vStartFirstTask
|
||||||
|
PUBLIC ulSetInterruptMask
|
||||||
|
PUBLIC vClearInterruptMask
|
||||||
|
PUBLIC PendSV_Handler
|
||||||
|
PUBLIC SVC_Handler
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*---------------- Unprivileged Functions -------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SECTION .text:CODE:NOROOT(2)
|
||||||
|
THUMB
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
xIsPrivileged:
|
||||||
|
mrs r0, control /* r0 = CONTROL. */
|
||||||
|
tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||||
|
ite ne
|
||||||
|
movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||||
|
moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */
|
||||||
|
bx lr /* Return. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vResetPrivilege:
|
||||||
|
mrs r0, control /* r0 = CONTROL. */
|
||||||
|
orr r0, r0, #1 /* r0 = r0 | 1. */
|
||||||
|
msr control, r0 /* CONTROL = r0. */
|
||||||
|
bx lr /* Return to the caller. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*----------------- Privileged Functions --------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SECTION privileged_functions:CODE:NOROOT(2)
|
||||||
|
THUMB
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
vRestoreContextOfFirstTask:
|
||||||
|
program_mpu_first_task:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r2] /* r0 = pxCurrentTCB. */
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
bic r2, #1 /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Disable MPU. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
str r1, [r2] /* Program MAIR0. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
|
||||||
|
movs r3, #4 /* r3 = 4. */
|
||||||
|
str r3, [r1] /* Program RNR = 4. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
movs r3, #8 /* r3 = 8. */
|
||||||
|
str r3, [r1] /* Program RNR = 8. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
movs r3, #12 /* r3 = 12. */
|
||||||
|
str r3, [r1] /* Program RNR = 12. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||||
|
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
orr r2, #1 /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
|
restore_context_first_task:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r2] /* r0 = pxCurrentTCB.*/
|
||||||
|
ldr r1, [r0] /* r1 = Location of saved context in TCB. */
|
||||||
|
|
||||||
|
restore_special_regs_first_task:
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
|
||||||
|
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
msr PAC_KEY_P_1, r3
|
||||||
|
msr PAC_KEY_P_2, r4
|
||||||
|
msr PAC_KEY_P_3, r5
|
||||||
|
clrm {r2-r5} /* Clear r2-r5. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
|
||||||
|
msr psp, r2
|
||||||
|
msr psplim, r3
|
||||||
|
msr control, r4
|
||||||
|
|
||||||
|
restore_general_regs_first_task:
|
||||||
|
ldmdb r1!, {r4-r11} /* r4-r11 contain hardware saved context. */
|
||||||
|
stmia r2!, {r4-r11} /* Copy the hardware saved context on the task stack. */
|
||||||
|
ldmdb r1!, {r4-r11} /* r4-r11 restored. */
|
||||||
|
|
||||||
|
restore_context_done_first_task:
|
||||||
|
str r1, [r0] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
vRestoreContextOfFirstTask:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||||
|
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
|
||||||
|
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
msr PAC_KEY_P_2, r2
|
||||||
|
msr PAC_KEY_P_1, r3
|
||||||
|
msr PAC_KEY_P_0, r4
|
||||||
|
clrm {r1-r4} /* Clear r1-r4. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
|
||||||
|
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||||
|
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||||
|
mrs r1, control /* Obtain current control register value. */
|
||||||
|
orrs r1, r1, #2 /* r1 = r1 | 0x2 - Set the second bit to use the program stack pointe (PSP). */
|
||||||
|
msr control, r1 /* Write back the new control register value. */
|
||||||
|
adds r0, #32 /* Discard everything up to r0. */
|
||||||
|
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||||
|
isb
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||||
|
bx r2 /* Finally, branch to EXC_RETURN. */
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vRaisePrivilege:
|
||||||
|
mrs r0, control /* Read the CONTROL register. */
|
||||||
|
bic r0, r0, #1 /* Clear the bit 0. */
|
||||||
|
msr control, r0 /* Write back the new CONTROL value. */
|
||||||
|
bx lr /* Return to the caller. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vStartFirstTask:
|
||||||
|
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||||
|
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||||
|
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||||
|
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||||
|
cpsie i /* Globally enable interrupts. */
|
||||||
|
cpsie f
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
svc 102 /* System call to start the first task. portSVC_START_SCHEDULER = 102. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
ulSetInterruptMask:
|
||||||
|
mrs r0, basepri /* r0 = basepri. Return original basepri value. */
|
||||||
|
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r1 /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
bx lr /* Return. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vClearInterruptMask:
|
||||||
|
msr basepri, r0 /* basepri = ulMask. */
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
bx lr /* Return. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
PendSV_Handler:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r2] /* r0 = pxCurrentTCB. */
|
||||||
|
ldr r1, [r0] /* r1 = Location in TCB where the context should be saved. */
|
||||||
|
mrs r2, psp /* r2 = PSP. */
|
||||||
|
|
||||||
|
save_general_regs:
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
add r2, r2, #0x20 /* Move r2 to location where s0 is saved. */
|
||||||
|
tst lr, #0x10
|
||||||
|
ittt eq
|
||||||
|
vstmiaeq r1!, {s16-s31} /* Store s16-s31. */
|
||||||
|
vldmiaeq r2, {s0-s16} /* Copy hardware saved FP context into s0-s16. */
|
||||||
|
vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */
|
||||||
|
sub r2, r2, #0x20 /* Set r2 back to the location of hardware saved context. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
stmia r1!, {r4-r11} /* Store r4-r11. */
|
||||||
|
ldmia r2, {r4-r11} /* Copy the hardware saved context into r4-r11. */
|
||||||
|
stmia r1!, {r4-r11} /* Store the hardware saved context. */
|
||||||
|
|
||||||
|
save_special_regs:
|
||||||
|
mrs r3, psplim /* r3 = PSPLIM. */
|
||||||
|
mrs r4, control /* r4 = CONTROL. */
|
||||||
|
stmia r1!, {r2-r4, lr} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
mrs r2, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
|
||||||
|
mrs r3, PAC_KEY_P_1
|
||||||
|
mrs r4, PAC_KEY_P_2
|
||||||
|
mrs r5, PAC_KEY_P_3
|
||||||
|
stmia r1!, {r2-r5} /* Store the task's dedicated PAC key on the task's context. */
|
||||||
|
clrm {r2-r5} /* Clear r2-r5. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
|
||||||
|
str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */
|
||||||
|
|
||||||
|
select_next_task:
|
||||||
|
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r0 /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
mov r0, #0 /* r0 = 0. */
|
||||||
|
msr basepri, r0 /* Enable interrupts. */
|
||||||
|
|
||||||
|
program_mpu:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r2] /* r0 = pxCurrentTCB. */
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
bic r2, #1 /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Disable MPU. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||||
|
ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||||
|
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||||
|
str r1, [r2] /* Program MAIR0. */
|
||||||
|
|
||||||
|
adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||||
|
ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||||
|
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||||
|
|
||||||
|
movs r3, #4 /* r3 = 4. */
|
||||||
|
str r3, [r1] /* Program RNR = 4. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
|
||||||
|
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||||
|
movs r3, #8 /* r3 = 8. */
|
||||||
|
str r3, [r1] /* Program RNR = 8. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
movs r3, #12 /* r3 = 12. */
|
||||||
|
str r3, [r1] /* Program RNR = 12. */
|
||||||
|
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||||
|
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||||
|
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||||
|
|
||||||
|
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||||
|
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||||
|
orr r2, #1 /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
|
||||||
|
str r2, [r1] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
|
restore_context:
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r0, [r2] /* r0 = pxCurrentTCB.*/
|
||||||
|
ldr r1, [r0] /* r1 = Location of saved context in TCB. */
|
||||||
|
|
||||||
|
restore_special_regs:
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
|
||||||
|
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
msr PAC_KEY_P_1, r3
|
||||||
|
msr PAC_KEY_P_2, r4
|
||||||
|
msr PAC_KEY_P_3, r5
|
||||||
|
clrm {r2-r5} /* Clear r2-r5. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
|
||||||
|
msr psp, r2
|
||||||
|
msr psplim, r3
|
||||||
|
msr control, r4
|
||||||
|
|
||||||
|
restore_general_regs:
|
||||||
|
ldmdb r1!, {r4-r11} /* r4-r11 contain hardware saved context. */
|
||||||
|
stmia r2!, {r4-r11} /* Copy the hardware saved context on the task stack. */
|
||||||
|
ldmdb r1!, {r4-r11} /* r4-r11 restored. */
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
tst lr, #0x10
|
||||||
|
ittt eq
|
||||||
|
vldmdbeq r1!, {s0-s16} /* s0-s16 contain hardware saved FP context. */
|
||||||
|
vstmiaeq r2!, {s0-s16} /* Copy hardware saved FP context on the task stack. */
|
||||||
|
vldmdbeq r1!, {s16-s31} /* Restore s16-s31. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
|
||||||
|
restore_context_done:
|
||||||
|
str r1, [r0] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
|
||||||
|
PendSV_Handler:
|
||||||
|
mrs r0, psp /* Read PSP in r0. */
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||||
|
it eq
|
||||||
|
vstmdbeq r0!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
|
||||||
|
mrs r2, psplim /* r2 = PSPLIM. */
|
||||||
|
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||||
|
stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */
|
||||||
|
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
mrs r1, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
|
||||||
|
mrs r2, PAC_KEY_P_2
|
||||||
|
mrs r3, PAC_KEY_P_1
|
||||||
|
mrs r4, PAC_KEY_P_0
|
||||||
|
stmdb r0!, {r1-r4} /* Store the task's dedicated PAC key on the stack. */
|
||||||
|
clrm {r1-r4} /* Clear r1-r4. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||||
|
str r0, [r1] /* Save the new top of stack in TCB. */
|
||||||
|
|
||||||
|
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r0 /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
mov r0, #0 /* r0 = 0. */
|
||||||
|
msr basepri, r0 /* Enable interrupts. */
|
||||||
|
|
||||||
|
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||||
|
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||||
|
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||||
|
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
ldmia r0!, {r2-r5} /* Read task's dedicated PAC key from stack. */
|
||||||
|
msr PAC_KEY_P_3, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
|
||||||
|
msr PAC_KEY_P_2, r3
|
||||||
|
msr PAC_KEY_P_1, r4
|
||||||
|
msr PAC_KEY_P_0, r5
|
||||||
|
clrm {r2-r5} /* Clear r2-r5. */
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
|
||||||
|
ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
|
||||||
|
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
tst r3, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||||
|
it eq
|
||||||
|
vldmiaeq r0!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
|
||||||
|
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||||
|
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||||
|
bx r3
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||||
|
|
||||||
|
SVC_Handler:
|
||||||
|
tst lr, #4
|
||||||
|
ite eq
|
||||||
|
mrseq r0, msp
|
||||||
|
mrsne r0, psp
|
||||||
|
|
||||||
|
ldr r1, [r0, #24]
|
||||||
|
ldrb r2, [r1, #-2]
|
||||||
|
cmp r2, #NUM_SYSTEM_CALLS
|
||||||
|
blt syscall_enter
|
||||||
|
cmp r2, #104 /* portSVC_SYSTEM_CALL_EXIT. */
|
||||||
|
beq syscall_exit
|
||||||
|
b vPortSVCHandler_C
|
||||||
|
|
||||||
|
syscall_enter:
|
||||||
|
mov r1, lr
|
||||||
|
b vSystemCallEnter
|
||||||
|
|
||||||
|
syscall_exit:
|
||||||
|
mov r1, lr
|
||||||
|
b vSystemCallExit
|
||||||
|
|
||||||
|
#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
|
||||||
|
SVC_Handler:
|
||||||
|
tst lr, #4
|
||||||
|
ite eq
|
||||||
|
mrseq r0, msp
|
||||||
|
mrsne r0, psp
|
||||||
|
b vPortSVCHandler_C
|
||||||
|
|
||||||
|
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
END
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M33"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 0
|
||||||
|
#define portDONT_DISCARD __root
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#define configENABLE_MVE 0
|
||||||
|
#elif ( configENABLE_MVE != 0 )
|
||||||
|
#error configENABLE_MVE must be left undefined, or defined to 0 for the Cortex-M33.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M35P"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 0
|
||||||
|
#define portDONT_DISCARD __root
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#define configENABLE_MVE 0
|
||||||
|
#elif ( configENABLE_MVE != 0 )
|
||||||
|
#error configENABLE_MVE must be left undefined, or defined to 0 for the Cortex-M35.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
* Copyright (c) 2025 Arm Technology (China) Co., Ltd.All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#error configENABLE_MVE must be defined in FreeRTOSConfig.h. Set configENABLE_MVE to 1 to enable the MVE or 0 to disable the MVE.
|
||||||
|
#endif /* configENABLE_MVE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M52"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 1
|
||||||
|
#define portDONT_DISCARD __root
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+86
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#error configENABLE_MVE must be defined in FreeRTOSConfig.h. Set configENABLE_MVE to 1 to enable the MVE or 0 to disable the MVE.
|
||||||
|
#endif /* configENABLE_MVE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M55"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 1
|
||||||
|
#define portDONT_DISCARD __root
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+86
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#error configENABLE_MVE must be defined in FreeRTOSConfig.h. Set configENABLE_MVE to 1 to enable the MVE or 0 to disable the MVE.
|
||||||
|
#endif /* configENABLE_MVE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "Cortex-M85"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 1
|
||||||
|
#define portDONT_DISCARD __root
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
* Copyright (c) 2026 Arm Technology (China) Co., Ltd.All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_MVE
|
||||||
|
#error configENABLE_MVE must be defined in FreeRTOSConfig.h. Set configENABLE_MVE to 1 to enable the MVE or 0 to disable the MVE.
|
||||||
|
#endif /* configENABLE_MVE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portARCH_NAME "STAR-MC3"
|
||||||
|
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||||
|
#define portARMV8M_MINOR_VERSION 1
|
||||||
|
#define portDONT_DISCARD __root
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ARMv8-M common port configurations. */
|
||||||
|
#include "portmacrocommon.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PORT_ASM_H__
|
||||||
|
#define __PORT_ASM_H__
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
|
||||||
|
/* MPU wrappers includes. */
|
||||||
|
#include "mpu_wrappers.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Restore the context of the first task so that the first task starts
|
||||||
|
* executing.
|
||||||
|
*/
|
||||||
|
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether or not the processor is privileged.
|
||||||
|
*
|
||||||
|
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||||
|
*/
|
||||||
|
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||||
|
* register.
|
||||||
|
*
|
||||||
|
* @note This is a privileged function and should only be called from the kernel
|
||||||
|
* code.
|
||||||
|
*
|
||||||
|
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||||
|
* Bit[0] = 0 --> The processor is running privileged
|
||||||
|
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||||
|
*/
|
||||||
|
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||||
|
* register.
|
||||||
|
*
|
||||||
|
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||||
|
* Bit[0] = 0 --> The processor is running privileged
|
||||||
|
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||||
|
*/
|
||||||
|
void vResetPrivilege( void ) __attribute__( ( naked ) );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts the first task.
|
||||||
|
*/
|
||||||
|
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disables interrupts.
|
||||||
|
*/
|
||||||
|
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables interrupts.
|
||||||
|
*/
|
||||||
|
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PendSV Exception handler.
|
||||||
|
*/
|
||||||
|
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SVC Handler.
|
||||||
|
*/
|
||||||
|
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate a Secure context for the calling task.
|
||||||
|
*
|
||||||
|
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||||
|
* secure side for the calling task.
|
||||||
|
*/
|
||||||
|
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free the task's secure context.
|
||||||
|
*
|
||||||
|
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||||
|
*/
|
||||||
|
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
#endif /* __PORT_ASM_H__ */
|
||||||
@@ -0,0 +1,582 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
* Copyright 2024 Arm Limited and/or its affiliates
|
||||||
|
* <open-source-office@arm.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACROCOMMON_H
|
||||||
|
#define PORTMACROCOMMON_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||||
|
* and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef configENABLE_FPU
|
||||||
|
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||||
|
#endif /* configENABLE_FPU */
|
||||||
|
|
||||||
|
#ifndef configENABLE_MPU
|
||||||
|
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
|
||||||
|
#ifndef configENABLE_TRUSTZONE
|
||||||
|
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||||
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type definitions.
|
||||||
|
*/
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
#else
|
||||||
|
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture specifics.
|
||||||
|
*/
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
#define portNOP()
|
||||||
|
#define portINLINE __inline
|
||||||
|
#ifndef portFORCE_INLINE
|
||||||
|
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||||
|
#endif
|
||||||
|
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Extern declarations.
|
||||||
|
*/
|
||||||
|
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||||
|
|
||||||
|
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||||
|
|
||||||
|
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||||
|
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||||
|
|
||||||
|
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||||
|
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||||
|
|
||||||
|
#if ( configENABLE_TRUSTZONE == 1 )
|
||||||
|
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||||
|
extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||||
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||||
|
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
|
||||||
|
#if ( configENABLE_PAC == 1 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generates 128-bit task's random PAC key.
|
||||||
|
*
|
||||||
|
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
|
||||||
|
* filled with a 128-bit random number.
|
||||||
|
*/
|
||||||
|
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
|
||||||
|
|
||||||
|
#endif /* configENABLE_PAC */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief MPU specific constants.
|
||||||
|
*/
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
#define portUSING_MPU_WRAPPERS 1
|
||||||
|
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||||
|
#else
|
||||||
|
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
|
||||||
|
/* MPU settings that can be overridden in FreeRTOSConfig.h. */
|
||||||
|
#ifndef configTOTAL_MPU_REGIONS
|
||||||
|
/* Define to 8 for backward compatibility. */
|
||||||
|
#define configTOTAL_MPU_REGIONS ( 8UL )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* MPU regions. */
|
||||||
|
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||||
|
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||||
|
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||||
|
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||||
|
#define portSTACK_REGION ( 4UL )
|
||||||
|
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||||
|
#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL )
|
||||||
|
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||||
|
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||||
|
|
||||||
|
/* Device memory attributes used in MPU_MAIR registers.
|
||||||
|
*
|
||||||
|
* 8-bit values encoded as follows:
|
||||||
|
* Bit[7:4] - 0000 - Device Memory
|
||||||
|
* Bit[3:2] - 00 --> Device-nGnRnE
|
||||||
|
* 01 --> Device-nGnRE
|
||||||
|
* 10 --> Device-nGRE
|
||||||
|
* 11 --> Device-GRE
|
||||||
|
* Bit[1:0] - 00, Reserved.
|
||||||
|
*/
|
||||||
|
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||||
|
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||||
|
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||||
|
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||||
|
|
||||||
|
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||||
|
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||||
|
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||||
|
|
||||||
|
/* Attributes used in MPU_RBAR registers. */
|
||||||
|
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||||
|
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||||
|
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||||
|
|
||||||
|
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||||
|
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||||
|
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||||
|
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||||
|
|
||||||
|
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Settings to define an MPU region.
|
||||||
|
*/
|
||||||
|
typedef struct MPURegionSettings
|
||||||
|
{
|
||||||
|
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||||
|
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||||
|
} MPURegionSettings_t;
|
||||||
|
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||||
|
|
||||||
|
#ifndef configSYSTEM_CALL_STACK_SIZE
|
||||||
|
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief System call stack.
|
||||||
|
*/
|
||||||
|
typedef struct SYSTEM_CALL_STACK_INFO
|
||||||
|
{
|
||||||
|
uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ];
|
||||||
|
uint32_t * pulSystemCallStack;
|
||||||
|
uint32_t * pulSystemCallStackLimit;
|
||||||
|
uint32_t * pulTaskStack;
|
||||||
|
uint32_t ulLinkRegisterAtSystemCallEntry;
|
||||||
|
uint32_t ulStackLimitRegisterAtSystemCallEntry;
|
||||||
|
} xSYSTEM_CALL_STACK_INFO;
|
||||||
|
|
||||||
|
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief MPU settings as stored in the TCB.
|
||||||
|
*/
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
|
||||||
|
#if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
|
||||||
|
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
|
||||||
|
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
|
||||||
|
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
|
||||||
|
*
|
||||||
|
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
|
||||||
|
* 16 17 8 8 5 16 1
|
||||||
|
*/
|
||||||
|
#define MAX_CONTEXT_SIZE 71
|
||||||
|
|
||||||
|
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* +-----------+---------------+----------+-----------------+------------------------------+-----+
|
||||||
|
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | |
|
||||||
|
* | | | | PC, xPSR | CONTROL, EXC_RETURN | |
|
||||||
|
* +-----------+---------------+----------+-----------------+------------------------------+-----+
|
||||||
|
*
|
||||||
|
* <-----------><--------------><---------><----------------><-----------------------------><---->
|
||||||
|
* 16 17 8 8 5 1
|
||||||
|
*/
|
||||||
|
#define MAX_CONTEXT_SIZE 55
|
||||||
|
|
||||||
|
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
|
||||||
|
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
|
||||||
|
* | | | | PC, xPSR | EXC_RETURN | | |
|
||||||
|
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
|
||||||
|
*
|
||||||
|
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
|
||||||
|
* 16 17 8 8 4 16 1
|
||||||
|
*/
|
||||||
|
#define MAX_CONTEXT_SIZE 70
|
||||||
|
|
||||||
|
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* +-----------+---------------+----------+-----------------+----------------------+-----+
|
||||||
|
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | |
|
||||||
|
* | | | | PC, xPSR | EXC_RETURN | |
|
||||||
|
* +-----------+---------------+----------+-----------------+----------------------+-----+
|
||||||
|
*
|
||||||
|
* <-----------><--------------><---------><----------------><---------------------><---->
|
||||||
|
* 16 17 8 8 4 1
|
||||||
|
*/
|
||||||
|
#define MAX_CONTEXT_SIZE 54
|
||||||
|
|
||||||
|
#endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
|
||||||
|
|
||||||
|
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
|
||||||
|
|
||||||
|
#if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* +----------+-----------------+------------------------------+------------+-----+
|
||||||
|
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
|
||||||
|
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
|
||||||
|
* +----------+-----------------+------------------------------+------------+-----+
|
||||||
|
*
|
||||||
|
* <---------><----------------><------------------------------><-----------><---->
|
||||||
|
* 8 8 5 16 1
|
||||||
|
*/
|
||||||
|
#define MAX_CONTEXT_SIZE 38
|
||||||
|
|
||||||
|
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* +----------+-----------------+------------------------------+-----+
|
||||||
|
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | |
|
||||||
|
* | | PC, xPSR | CONTROL, EXC_RETURN | |
|
||||||
|
* +----------+-----------------+------------------------------+-----+
|
||||||
|
*
|
||||||
|
* <---------><----------------><------------------------------><---->
|
||||||
|
* 8 8 5 1
|
||||||
|
*/
|
||||||
|
#define MAX_CONTEXT_SIZE 22
|
||||||
|
|
||||||
|
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* +----------+-----------------+----------------------+------------+-----+
|
||||||
|
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
|
||||||
|
* | | PC, xPSR | EXC_RETURN | | |
|
||||||
|
* +----------+-----------------+----------------------+------------+-----+
|
||||||
|
*
|
||||||
|
* <---------><----------------><----------------------><-----------><---->
|
||||||
|
* 8 8 4 16 1
|
||||||
|
*/
|
||||||
|
#define MAX_CONTEXT_SIZE 37
|
||||||
|
|
||||||
|
#else /* #if( configENABLE_TRUSTZONE == 1 ) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* +----------+-----------------+----------------------+-----+
|
||||||
|
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | |
|
||||||
|
* | | PC, xPSR | EXC_RETURN | |
|
||||||
|
* +----------+-----------------+----------------------+-----+
|
||||||
|
*
|
||||||
|
* <---------><----------------><----------------------><---->
|
||||||
|
* 8 8 4 1
|
||||||
|
*/
|
||||||
|
#define MAX_CONTEXT_SIZE 21
|
||||||
|
|
||||||
|
#endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
|
||||||
|
|
||||||
|
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
|
||||||
|
|
||||||
|
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
|
||||||
|
#define portSTACK_FRAME_HAS_PADDING_FLAG ( 1UL << 0UL )
|
||||||
|
#define portTASK_IS_PRIVILEGED_FLAG ( 1UL << 1UL )
|
||||||
|
|
||||||
|
/* Size of an Access Control List (ACL) entry in bits. */
|
||||||
|
#define portACL_ENTRY_SIZE_BITS ( 32U )
|
||||||
|
|
||||||
|
typedef struct MPU_SETTINGS
|
||||||
|
{
|
||||||
|
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||||
|
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||||
|
uint32_t ulContext[ MAX_CONTEXT_SIZE ];
|
||||||
|
uint32_t ulTaskFlags;
|
||||||
|
|
||||||
|
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||||
|
xSYSTEM_CALL_STACK_INFO xSystemCallStackInfo;
|
||||||
|
#if ( configENABLE_ACCESS_CONTROL_LIST == 1 )
|
||||||
|
uint32_t ulAccessControlList[ ( configPROTECTED_KERNEL_OBJECT_POOL_SIZE / portACL_ENTRY_SIZE_BITS ) + 1 ];
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
} xMPU_SETTINGS;
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU == 1 */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Validate priority of ISRs that are allowed to call FreeRTOS
|
||||||
|
* system calls.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
#if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SVC numbers.
|
||||||
|
*/
|
||||||
|
#define portSVC_ALLOCATE_SECURE_CONTEXT 100
|
||||||
|
#define portSVC_FREE_SECURE_CONTEXT 101
|
||||||
|
#define portSVC_START_SCHEDULER 102
|
||||||
|
#define portSVC_RAISE_PRIVILEGE 103
|
||||||
|
#define portSVC_SYSTEM_CALL_EXIT 104
|
||||||
|
#define portSVC_YIELD 105
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Scheduler utilities.
|
||||||
|
*/
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
#define portYIELD() __asm volatile ( "svc %0" ::"i" ( portSVC_YIELD ) : "memory" )
|
||||||
|
#define portYIELD_WITHIN_API() vPortYield()
|
||||||
|
#else
|
||||||
|
#define portYIELD() vPortYield()
|
||||||
|
#define portYIELD_WITHIN_API() vPortYield()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||||
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if( xSwitchRequired ) \
|
||||||
|
{ \
|
||||||
|
traceISR_EXIT_TO_SCHEDULER(); \
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
traceISR_EXIT(); \
|
||||||
|
} \
|
||||||
|
} while( 0 )
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Critical section management.
|
||||||
|
*/
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 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
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
|
*/
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_TRUSTZONE == 1 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate a secure context for the task.
|
||||||
|
*
|
||||||
|
* Tasks are not created with a secure context. Any task that is going to call
|
||||||
|
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||||
|
* secure context before it calls any secure function.
|
||||||
|
*
|
||||||
|
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||||
|
*/
|
||||||
|
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when a task is deleted to delete the task's secure context,
|
||||||
|
* if it has one.
|
||||||
|
*
|
||||||
|
* @param[in] pxTCB The TCB of the task being deleted.
|
||||||
|
*/
|
||||||
|
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||||
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether or not the processor is privileged.
|
||||||
|
*
|
||||||
|
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||||
|
*/
|
||||||
|
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Raise an SVC request to raise privilege.
|
||||||
|
*
|
||||||
|
* The SVC handler checks that the SVC was raised from a system call and only
|
||||||
|
* then it raises the privilege. If this is called from any other place,
|
||||||
|
* the privilege is not raised.
|
||||||
|
*/
|
||||||
|
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||||
|
* register.
|
||||||
|
*/
|
||||||
|
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||||
|
#else
|
||||||
|
#define portIS_PRIVILEGED()
|
||||||
|
#define portRAISE_PRIVILEGE()
|
||||||
|
#define portRESET_PRIVILEGE()
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
|
||||||
|
extern BaseType_t xPortIsTaskPrivileged( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether or not the calling task is privileged.
|
||||||
|
*
|
||||||
|
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
|
||||||
|
*/
|
||||||
|
#define portIS_TASK_PRIVILEGED() xPortIsTaskPrivileged()
|
||||||
|
|
||||||
|
#endif /* configENABLE_MPU == 1 */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Barriers.
|
||||||
|
*/
|
||||||
|
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||||
|
* based on whether or not Mainline extension is implemented. */
|
||||||
|
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||||
|
#if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
|
||||||
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||||
|
#else
|
||||||
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
|
||||||
|
#endif
|
||||||
|
#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Port-optimised task selection.
|
||||||
|
*/
|
||||||
|
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Count the number of leading zeros in a 32-bit value.
|
||||||
|
*/
|
||||||
|
static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap )
|
||||||
|
{
|
||||||
|
uint32_t ulReturn;
|
||||||
|
|
||||||
|
__asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||||
|
|
||||||
|
return ulReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 different priorities as tasks that share a priority will time slice.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 )
|
||||||
|
#error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 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 ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the priority of the highest-priority task that is ready to execute.
|
||||||
|
*/
|
||||||
|
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||||
|
|
||||||
|
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACROCOMMON_H */
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
This directory tree contains the master copy of the FreeRTOS Armv8-M and
|
||||||
|
Armv8.1-M ports.
|
||||||
|
Do not use the files located here! These file are copied into separate
|
||||||
|
FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3]_NNN directories
|
||||||
|
prior to each FreeRTOS release.
|
||||||
|
|
||||||
|
If your Armv8-M/Armv8.1-M application uses TrustZone then use the files from the
|
||||||
|
FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3] directories.
|
||||||
|
|
||||||
|
If your Armv8-M/Armv8.1-M application does not use TrustZone then use the files from
|
||||||
|
the FreeRTOS/Source/portable/[compiler]/ARM_[CM23|CM33|CM52|CM55|CM85|STAR_MC3]_NTZ directories.
|
||||||
+99
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Secure context includes. */
|
||||||
|
#include "secure_context.h"
|
||||||
|
|
||||||
|
/* Secure port macros. */
|
||||||
|
#include "secure_port_macros.h"
|
||||||
|
|
||||||
|
#if ( configENABLE_FPU == 1 )
|
||||||
|
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||||
|
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||||
|
|
||||||
|
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
|
||||||
|
{
|
||||||
|
/* pxSecureContext value is in r0. */
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||||
|
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||||
|
" ldmia r0!, {r1, r2} \n" /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||||
|
" \n"
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||||
|
" msr control, r3 \n" /* CONTROL = r3. */
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
" \n"
|
||||||
|
" msr psplim, r2 \n" /* PSPLIM = r2. */
|
||||||
|
" msr psp, r1 \n" /* PSP = r1. */
|
||||||
|
" \n"
|
||||||
|
" load_ctx_therad_mode: \n"
|
||||||
|
" bx lr \n"
|
||||||
|
" \n"
|
||||||
|
::: "r0", "r1", "r2"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )
|
||||||
|
{
|
||||||
|
/* pxSecureContext value is in r0. */
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||||
|
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||||
|
" mrs r1, psp \n" /* r1 = PSP. */
|
||||||
|
" \n"
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||||
|
" subs r1, r1, #4 \n" /* Make space for the CONTROL value on the stack. */
|
||||||
|
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||||
|
" stmia r1!, {r2} \n" /* Store CONTROL value on the stack. */
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
" \n"
|
||||||
|
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
|
||||||
|
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
|
||||||
|
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||||
|
" \n"
|
||||||
|
" save_ctx_therad_mode: \n"
|
||||||
|
" bx lr \n"
|
||||||
|
" \n"
|
||||||
|
::"i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
+97
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Secure context includes. */
|
||||||
|
#include "secure_context.h"
|
||||||
|
|
||||||
|
/* Secure port macros. */
|
||||||
|
#include "secure_port_macros.h"
|
||||||
|
|
||||||
|
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||||
|
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||||
|
|
||||||
|
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
|
||||||
|
{
|
||||||
|
/* pxSecureContext value is in r0. */
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||||
|
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||||
|
" ldmia r0!, {r1, r2} \n" /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||||
|
" \n"
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||||
|
" msr control, r3 \n" /* CONTROL = r3. */
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
" \n"
|
||||||
|
" msr psplim, r2 \n" /* PSPLIM = r2. */
|
||||||
|
" msr psp, r1 \n" /* PSP = r1. */
|
||||||
|
" \n"
|
||||||
|
" load_ctx_therad_mode: \n"
|
||||||
|
" bx lr \n"
|
||||||
|
" \n"
|
||||||
|
::: "r0", "r1", "r2"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )
|
||||||
|
{
|
||||||
|
/* pxSecureContext value is in r0. */
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" .syntax unified \n"
|
||||||
|
" \n"
|
||||||
|
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||||
|
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||||
|
" mrs r1, psp \n" /* r1 = PSP. */
|
||||||
|
" \n"
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
" vstmdb r1!, {s0} \n" /* Trigger the deferred stacking of FPU registers. */
|
||||||
|
" vldmia r1!, {s0} \n" /* Nullify the effect of the previous statement. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
" \n"
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||||
|
" stmdb r1!, {r2} \n" /* Store CONTROL value on the stack. */
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
" \n"
|
||||||
|
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||||
|
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
|
||||||
|
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
|
||||||
|
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||||
|
" \n"
|
||||||
|
" save_ctx_therad_mode: \n"
|
||||||
|
" bx lr \n"
|
||||||
|
" \n"
|
||||||
|
::"i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
SECTION .text:CODE:NOROOT(2)
|
||||||
|
THUMB
|
||||||
|
|
||||||
|
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||||
|
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||||
|
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||||
|
the code is included in C files but excluded by the preprocessor in assembly
|
||||||
|
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||||
|
#include "FreeRTOSConfig.h"
|
||||||
|
|
||||||
|
PUBLIC SecureContext_LoadContextAsm
|
||||||
|
PUBLIC SecureContext_SaveContextAsm
|
||||||
|
|
||||||
|
#if ( configENABLE_FPU == 1 )
|
||||||
|
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SecureContext_LoadContextAsm:
|
||||||
|
/* pxSecureContext value is in r0. */
|
||||||
|
mrs r1, ipsr /* r1 = IPSR. */
|
||||||
|
cbz r1, load_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||||
|
ldmia r0!, {r1, r2} /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
ldmia r1!, {r3} /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||||
|
msr control, r3 /* CONTROL = r3. */
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
|
||||||
|
msr psplim, r2 /* PSPLIM = r2. */
|
||||||
|
msr psp, r1 /* PSP = r1. */
|
||||||
|
|
||||||
|
load_ctx_therad_mode:
|
||||||
|
bx lr
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SecureContext_SaveContextAsm:
|
||||||
|
/* pxSecureContext value is in r0. */
|
||||||
|
mrs r1, ipsr /* r1 = IPSR. */
|
||||||
|
cbz r1, save_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||||
|
mrs r1, psp /* r1 = PSP. */
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
mrs r2, control /* r2 = CONTROL. */
|
||||||
|
subs r1, r1, #4 /* Make space for the CONTROL value on the stack. */
|
||||||
|
str r1, [r0] /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||||
|
stmia r1!, {r2} /* Store CONTROL value on the stack. */
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
str r1, [r0] /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
|
||||||
|
movs r1, #0 /* r1 = securecontextNO_STACK. */
|
||||||
|
msr psplim, r1 /* PSPLIM = securecontextNO_STACK. */
|
||||||
|
msr psp, r1 /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||||
|
|
||||||
|
save_ctx_therad_mode:
|
||||||
|
bx lr
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
END
|
||||||
+86
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
SECTION .text:CODE:NOROOT(2)
|
||||||
|
THUMB
|
||||||
|
|
||||||
|
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||||
|
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||||
|
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||||
|
the code is included in C files but excluded by the preprocessor in assembly
|
||||||
|
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||||
|
#include "FreeRTOSConfig.h"
|
||||||
|
|
||||||
|
PUBLIC SecureContext_LoadContextAsm
|
||||||
|
PUBLIC SecureContext_SaveContextAsm
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SecureContext_LoadContextAsm:
|
||||||
|
/* pxSecureContext value is in r0. */
|
||||||
|
mrs r1, ipsr /* r1 = IPSR. */
|
||||||
|
cbz r1, load_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||||
|
ldmia r0!, {r1, r2} /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
ldmia r1!, {r3} /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||||
|
msr control, r3 /* CONTROL = r3. */
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
|
||||||
|
msr psplim, r2 /* PSPLIM = r2. */
|
||||||
|
msr psp, r1 /* PSP = r1. */
|
||||||
|
|
||||||
|
load_ctx_therad_mode:
|
||||||
|
bx lr
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
SecureContext_SaveContextAsm:
|
||||||
|
/* pxSecureContext value is in r0. */
|
||||||
|
mrs r1, ipsr /* r1 = IPSR. */
|
||||||
|
cbz r1, save_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||||
|
mrs r1, psp /* r1 = PSP. */
|
||||||
|
|
||||||
|
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||||
|
vstmdb r1!, {s0} /* Trigger the deferred stacking of FPU registers. */
|
||||||
|
vldmia r1!, {s0} /* Nullify the effect of the previous statement. */
|
||||||
|
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
mrs r2, control /* r2 = CONTROL. */
|
||||||
|
stmdb r1!, {r2} /* Store CONTROL value on the stack. */
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
|
||||||
|
str r1, [r0] /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||||
|
movs r1, #0 /* r1 = securecontextNO_STACK. */
|
||||||
|
msr psplim, r1 /* PSPLIM = securecontextNO_STACK. */
|
||||||
|
msr psp, r1 /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||||
|
|
||||||
|
save_ctx_therad_mode:
|
||||||
|
bx lr
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
END
|
||||||
@@ -0,0 +1,354 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Secure context includes. */
|
||||||
|
#include "secure_context.h"
|
||||||
|
|
||||||
|
/* Secure heap includes. */
|
||||||
|
#include "secure_heap.h"
|
||||||
|
|
||||||
|
/* Secure port macros. */
|
||||||
|
#include "secure_port_macros.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CONTROL value for privileged tasks.
|
||||||
|
*
|
||||||
|
* Bit[0] - 0 --> Thread mode is privileged.
|
||||||
|
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||||
|
*/
|
||||||
|
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CONTROL value for un-privileged tasks.
|
||||||
|
*
|
||||||
|
* Bit[0] - 1 --> Thread mode is un-privileged.
|
||||||
|
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||||
|
*/
|
||||||
|
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of stack seal values in bytes.
|
||||||
|
*/
|
||||||
|
#define securecontextSTACK_SEAL_SIZE 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stack seal value as recommended by ARM.
|
||||||
|
*/
|
||||||
|
#define securecontextSTACK_SEAL_VALUE 0xFEF5EDA5
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of secure contexts.
|
||||||
|
*/
|
||||||
|
#ifndef secureconfigMAX_SECURE_CONTEXTS
|
||||||
|
#define secureconfigMAX_SECURE_CONTEXTS 8UL
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pre-allocated array of secure contexts.
|
||||||
|
*/
|
||||||
|
SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a free secure context for a task from the secure context pool (xSecureContexts).
|
||||||
|
*
|
||||||
|
* This function ensures that only one secure context is allocated for a task.
|
||||||
|
*
|
||||||
|
* @param[in] pvTaskHandle The task handle for which the secure context is allocated.
|
||||||
|
*
|
||||||
|
* @return Index of a free secure context in the xSecureContexts array.
|
||||||
|
*/
|
||||||
|
static uint32_t ulGetSecureContext( void * pvTaskHandle );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return the secure context to the secure context pool (xSecureContexts).
|
||||||
|
*
|
||||||
|
* @param[in] ulSecureContextIndex Index of the context in the xSecureContexts array.
|
||||||
|
*/
|
||||||
|
static void vReturnSecureContext( uint32_t ulSecureContextIndex );
|
||||||
|
|
||||||
|
/* These are implemented in assembly. */
|
||||||
|
extern void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext );
|
||||||
|
extern void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext );
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static uint32_t ulGetSecureContext( void * pvTaskHandle )
|
||||||
|
{
|
||||||
|
/* Start with invalid index. */
|
||||||
|
uint32_t i, ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
|
||||||
|
|
||||||
|
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
|
||||||
|
{
|
||||||
|
if( ( xSecureContexts[ i ].pucCurrentStackPointer == NULL ) &&
|
||||||
|
( xSecureContexts[ i ].pucStackLimit == NULL ) &&
|
||||||
|
( xSecureContexts[ i ].pucStackStart == NULL ) &&
|
||||||
|
( xSecureContexts[ i ].pvTaskHandle == NULL ) &&
|
||||||
|
( ulSecureContextIndex == secureconfigMAX_SECURE_CONTEXTS ) )
|
||||||
|
{
|
||||||
|
ulSecureContextIndex = i;
|
||||||
|
}
|
||||||
|
else if( xSecureContexts[ i ].pvTaskHandle == pvTaskHandle )
|
||||||
|
{
|
||||||
|
/* A task can only have one secure context. Do not allocate a second
|
||||||
|
* context for the same task. */
|
||||||
|
ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ulSecureContextIndex;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vReturnSecureContext( uint32_t ulSecureContextIndex )
|
||||||
|
{
|
||||||
|
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;
|
||||||
|
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;
|
||||||
|
xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;
|
||||||
|
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = NULL;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
|
||||||
|
{
|
||||||
|
uint32_t ulIPSR, i;
|
||||||
|
static uint32_t ulSecureContextsInitialized = 0;
|
||||||
|
|
||||||
|
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||||
|
secureportREAD_IPSR( ulIPSR );
|
||||||
|
|
||||||
|
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||||
|
* when the processor is running in the Thread Mode. */
|
||||||
|
if( ( ulIPSR != 0 ) && ( ulSecureContextsInitialized == 0 ) )
|
||||||
|
{
|
||||||
|
/* Ensure to initialize secure contexts only once. */
|
||||||
|
ulSecureContextsInitialized = 1;
|
||||||
|
|
||||||
|
/* No stack for thread mode until a task's context is loaded. */
|
||||||
|
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||||
|
secureportSET_PSP( securecontextNO_STACK );
|
||||||
|
|
||||||
|
/* Initialize all secure contexts. */
|
||||||
|
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
|
||||||
|
{
|
||||||
|
xSecureContexts[ i ].pucCurrentStackPointer = NULL;
|
||||||
|
xSecureContexts[ i ].pucStackLimit = NULL;
|
||||||
|
xSecureContexts[ i ].pucStackStart = NULL;
|
||||||
|
xSecureContexts[ i ].pvTaskHandle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
{
|
||||||
|
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||||
|
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||||
|
}
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
{
|
||||||
|
/* Configure thread mode to use PSP and to be privileged. */
|
||||||
|
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||||
|
}
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||||
|
uint32_t ulIsTaskPrivileged,
|
||||||
|
void * pvTaskHandle )
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||||
|
void * pvTaskHandle )
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
{
|
||||||
|
uint8_t * pucStackMemory = NULL;
|
||||||
|
uint8_t * pucStackLimit;
|
||||||
|
uint32_t ulIPSR, ulSecureContextIndex;
|
||||||
|
SecureContextHandle_t xSecureContextHandle = securecontextINVALID_CONTEXT_ID;
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
uint32_t * pulCurrentStackPointer = NULL;
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
|
||||||
|
/* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
|
||||||
|
* Register (PSPLIM) value. */
|
||||||
|
secureportREAD_IPSR( ulIPSR );
|
||||||
|
secureportREAD_PSPLIM( pucStackLimit );
|
||||||
|
|
||||||
|
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||||
|
* when the processor is running in the Thread Mode.
|
||||||
|
* Also do nothing, if a secure context us already loaded. PSPLIM is set to
|
||||||
|
* securecontextNO_STACK when no secure context is loaded. */
|
||||||
|
if( ( ulIPSR != 0 ) && ( pucStackLimit == securecontextNO_STACK ) )
|
||||||
|
{
|
||||||
|
/* Obtain a free secure context. */
|
||||||
|
ulSecureContextIndex = ulGetSecureContext( pvTaskHandle );
|
||||||
|
|
||||||
|
/* Were we able to get a free context? */
|
||||||
|
if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
|
||||||
|
{
|
||||||
|
/* Allocate the stack space. */
|
||||||
|
pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
|
||||||
|
|
||||||
|
if( pucStackMemory != NULL )
|
||||||
|
{
|
||||||
|
/* Since stack grows down, the starting point will be the last
|
||||||
|
* location. Note that this location is next to the last
|
||||||
|
* allocated byte for stack (excluding the space for seal values)
|
||||||
|
* because the hardware decrements the stack pointer before
|
||||||
|
* writing i.e. if stack pointer is 0x2, a push operation will
|
||||||
|
* decrement the stack pointer to 0x1 and then write at 0x1. */
|
||||||
|
xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||||
|
|
||||||
|
/* Seal the created secure process stack. */
|
||||||
|
*( uint32_t * ) ( pucStackMemory + ulSecureStackSize ) = securecontextSTACK_SEAL_VALUE;
|
||||||
|
*( uint32_t * ) ( pucStackMemory + ulSecureStackSize + 4 ) = securecontextSTACK_SEAL_VALUE;
|
||||||
|
|
||||||
|
/* The stack cannot go beyond this location. This value is
|
||||||
|
* programmed in the PSPLIM register on context switch.*/
|
||||||
|
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;
|
||||||
|
|
||||||
|
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = pvTaskHandle;
|
||||||
|
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
{
|
||||||
|
/* Store the correct CONTROL value for the task on the stack.
|
||||||
|
* This value is programmed in the CONTROL register on
|
||||||
|
* context switch. */
|
||||||
|
pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;
|
||||||
|
pulCurrentStackPointer--;
|
||||||
|
|
||||||
|
if( ulIsTaskPrivileged )
|
||||||
|
{
|
||||||
|
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the current stack pointer. This value is programmed in
|
||||||
|
* the PSP register on context switch. */
|
||||||
|
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||||
|
}
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
{
|
||||||
|
/* Current SP is set to the starting of the stack. This
|
||||||
|
* value programmed in the PSP register on context switch. */
|
||||||
|
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;
|
||||||
|
}
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
|
||||||
|
/* Ensure to never return 0 as a valid context handle. */
|
||||||
|
xSecureContextHandle = ulSecureContextIndex + 1UL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return xSecureContextHandle;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle,
|
||||||
|
void * pvTaskHandle )
|
||||||
|
{
|
||||||
|
uint32_t ulIPSR, ulSecureContextIndex;
|
||||||
|
|
||||||
|
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||||
|
secureportREAD_IPSR( ulIPSR );
|
||||||
|
|
||||||
|
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||||
|
* when the processor is running in the Thread Mode. */
|
||||||
|
if( ulIPSR != 0 )
|
||||||
|
{
|
||||||
|
/* Only free if a valid context handle is passed. */
|
||||||
|
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||||
|
{
|
||||||
|
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||||
|
|
||||||
|
/* Ensure that the secure context being deleted is associated with
|
||||||
|
* the task. */
|
||||||
|
if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
|
||||||
|
{
|
||||||
|
/* Free the stack space. */
|
||||||
|
vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
|
||||||
|
|
||||||
|
/* Return the secure context back to the free secure contexts pool. */
|
||||||
|
vReturnSecureContext( ulSecureContextIndex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle,
|
||||||
|
void * pvTaskHandle )
|
||||||
|
{
|
||||||
|
uint8_t * pucStackLimit;
|
||||||
|
uint32_t ulSecureContextIndex;
|
||||||
|
|
||||||
|
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||||
|
{
|
||||||
|
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||||
|
|
||||||
|
secureportREAD_PSPLIM( pucStackLimit );
|
||||||
|
|
||||||
|
/* Ensure that no secure context is loaded and the task is loading it's
|
||||||
|
* own context. */
|
||||||
|
if( ( pucStackLimit == securecontextNO_STACK ) &&
|
||||||
|
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
|
||||||
|
{
|
||||||
|
SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle,
|
||||||
|
void * pvTaskHandle )
|
||||||
|
{
|
||||||
|
uint8_t * pucStackLimit;
|
||||||
|
uint32_t ulSecureContextIndex;
|
||||||
|
|
||||||
|
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||||
|
{
|
||||||
|
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||||
|
|
||||||
|
secureportREAD_PSPLIM( pucStackLimit );
|
||||||
|
|
||||||
|
/* Ensure that task's context is loaded and the task is saving it's own
|
||||||
|
* context. */
|
||||||
|
if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
|
||||||
|
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
|
||||||
|
{
|
||||||
|
SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SECURE_CONTEXT_H__
|
||||||
|
#define __SECURE_CONTEXT_H__
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* FreeRTOS includes. */
|
||||||
|
#include "FreeRTOSConfig.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PSP value when no secure context is loaded.
|
||||||
|
*/
|
||||||
|
#define securecontextNO_STACK 0x0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Invalid context ID.
|
||||||
|
*/
|
||||||
|
#define securecontextINVALID_CONTEXT_ID 0UL
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure to represent a secure context.
|
||||||
|
*
|
||||||
|
* @note Since stack grows down, pucStackStart is the highest address while
|
||||||
|
* pucStackLimit is the first address of the allocated memory.
|
||||||
|
*/
|
||||||
|
typedef struct SecureContext
|
||||||
|
{
|
||||||
|
uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||||
|
uint8_t * pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||||
|
uint8_t * pucStackStart; /**< First location of the stack memory. */
|
||||||
|
void * pvTaskHandle; /**< Task handle of the task this context is associated with. */
|
||||||
|
} SecureContext_t;
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opaque handle for a secure context.
|
||||||
|
*/
|
||||||
|
typedef uint32_t SecureContextHandle_t;
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the secure context management system.
|
||||||
|
*
|
||||||
|
* PSP is set to NULL and therefore a task must allocate and load a context
|
||||||
|
* before calling any secure side function in the thread mode.
|
||||||
|
*
|
||||||
|
* @note This function must be called in the handler mode. It is no-op if called
|
||||||
|
* in the thread mode.
|
||||||
|
*/
|
||||||
|
void SecureContext_Init( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocates a context on the secure side.
|
||||||
|
*
|
||||||
|
* @note This function must be called in the handler mode. It is no-op if called
|
||||||
|
* in the thread mode.
|
||||||
|
*
|
||||||
|
* @param[in] ulSecureStackSize Size of the stack to allocate on secure side.
|
||||||
|
* @param[in] ulIsTaskPrivileged 1 if the calling task is privileged, 0 otherwise.
|
||||||
|
*
|
||||||
|
* @return Opaque context handle if context is successfully allocated, NULL
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
#if ( configENABLE_MPU == 1 )
|
||||||
|
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||||
|
uint32_t ulIsTaskPrivileged,
|
||||||
|
void * pvTaskHandle );
|
||||||
|
#else /* configENABLE_MPU */
|
||||||
|
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||||
|
void * pvTaskHandle );
|
||||||
|
#endif /* configENABLE_MPU */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Frees the given context.
|
||||||
|
*
|
||||||
|
* @note This function must be called in the handler mode. It is no-op if called
|
||||||
|
* in the thread mode.
|
||||||
|
*
|
||||||
|
* @param[in] xSecureContextHandle Context handle corresponding to the
|
||||||
|
* context to be freed.
|
||||||
|
*/
|
||||||
|
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle,
|
||||||
|
void * pvTaskHandle );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Loads the given context.
|
||||||
|
*
|
||||||
|
* @note This function must be called in the handler mode. It is no-op if called
|
||||||
|
* in the thread mode.
|
||||||
|
*
|
||||||
|
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||||
|
* to be loaded.
|
||||||
|
*/
|
||||||
|
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle,
|
||||||
|
void * pvTaskHandle );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Saves the given context.
|
||||||
|
*
|
||||||
|
* @note This function must be called in the handler mode. It is no-op if called
|
||||||
|
* in the thread mode.
|
||||||
|
*
|
||||||
|
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||||
|
* to be saved.
|
||||||
|
*/
|
||||||
|
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle,
|
||||||
|
void * pvTaskHandle );
|
||||||
|
|
||||||
|
#endif /* __SECURE_CONTEXT_H__ */
|
||||||
@@ -0,0 +1,485 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Configuration includes. */
|
||||||
|
#include "FreeRTOSConfig.h"
|
||||||
|
|
||||||
|
/* Secure context heap includes. */
|
||||||
|
#include "secure_heap.h"
|
||||||
|
|
||||||
|
/* Secure port macros. */
|
||||||
|
#include "secure_port_macros.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Total heap size.
|
||||||
|
*/
|
||||||
|
#ifndef secureconfigTOTAL_HEAP_SIZE
|
||||||
|
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* No test marker by default. */
|
||||||
|
#ifndef mtCOVERAGE_TEST_MARKER
|
||||||
|
#define mtCOVERAGE_TEST_MARKER()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* No tracing by default. */
|
||||||
|
#ifndef traceMALLOC
|
||||||
|
#define traceMALLOC( pvReturn, xWantedSize )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* No tracing by default. */
|
||||||
|
#ifndef traceFREE
|
||||||
|
#define traceFREE( pv, xBlockSize )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Block sizes must not get too small. */
|
||||||
|
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||||
|
|
||||||
|
/* Assumes 8bit bytes! */
|
||||||
|
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||||
|
|
||||||
|
/* Max value that fits in a size_t type. */
|
||||||
|
#define secureheapSIZE_MAX ( ~( ( size_t ) 0 ) )
|
||||||
|
|
||||||
|
/* Check if adding a and b will result in overflow. */
|
||||||
|
#define secureheapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( secureheapSIZE_MAX - ( b ) ) )
|
||||||
|
|
||||||
|
/* MSB of the xBlockSize member of an BlockLink_t structure is used to track
|
||||||
|
* the allocation status of a block. When MSB of the xBlockSize member of
|
||||||
|
* an BlockLink_t structure is set then the block belongs to the application.
|
||||||
|
* When the bit is free the block is still part of the free heap space. */
|
||||||
|
#define secureheapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 ) )
|
||||||
|
#define secureheapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) == 0 )
|
||||||
|
#define secureheapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & secureheapBLOCK_ALLOCATED_BITMASK ) != 0 )
|
||||||
|
#define secureheapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= secureheapBLOCK_ALLOCATED_BITMASK )
|
||||||
|
#define secureheapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~secureheapBLOCK_ALLOCATED_BITMASK )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Allocate the memory for the heap. */
|
||||||
|
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||||
|
|
||||||
|
/* The application writer has already defined the array used for the RTOS
|
||||||
|
* heap - probably so it can be placed in a special segment or address. */
|
||||||
|
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||||
|
#else /* configAPPLICATION_ALLOCATED_HEAP */
|
||||||
|
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||||
|
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The linked list structure.
|
||||||
|
*
|
||||||
|
* This is used to link free blocks in order of their memory address.
|
||||||
|
*/
|
||||||
|
typedef struct A_BLOCK_LINK
|
||||||
|
{
|
||||||
|
struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
|
||||||
|
size_t xBlockSize; /**< The size of the free block. */
|
||||||
|
} BlockLink_t;
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called automatically to setup the required heap structures the first
|
||||||
|
* time pvPortMalloc() is called.
|
||||||
|
*/
|
||||||
|
static void prvHeapInit( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Inserts a block of memory that is being freed into the correct
|
||||||
|
* position in the list of free memory blocks.
|
||||||
|
*
|
||||||
|
* The block being freed will be merged with the block in front it and/or the
|
||||||
|
* block behind it if the memory blocks are adjacent to each other.
|
||||||
|
*
|
||||||
|
* @param[in] pxBlockToInsert The block being freed.
|
||||||
|
*/
|
||||||
|
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The size of the structure placed at the beginning of each allocated
|
||||||
|
* memory block must by correctly byte aligned.
|
||||||
|
*/
|
||||||
|
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( secureportBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a couple of list links to mark the start and end of the list.
|
||||||
|
*/
|
||||||
|
static BlockLink_t xStart;
|
||||||
|
static BlockLink_t * pxEnd = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Keeps track of the number of free bytes remaining, but says nothing
|
||||||
|
* about fragmentation.
|
||||||
|
*/
|
||||||
|
static size_t xFreeBytesRemaining = 0U;
|
||||||
|
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvHeapInit( void )
|
||||||
|
{
|
||||||
|
BlockLink_t * pxFirstFreeBlock;
|
||||||
|
uint8_t * pucAlignedHeap;
|
||||||
|
size_t uxAddress;
|
||||||
|
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||||
|
|
||||||
|
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||||
|
uxAddress = ( size_t ) ucHeap;
|
||||||
|
|
||||||
|
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||||
|
{
|
||||||
|
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||||
|
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||||
|
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||||
|
}
|
||||||
|
|
||||||
|
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||||
|
|
||||||
|
/* xStart is used to hold a pointer to the first item in the list of free
|
||||||
|
* blocks. The void cast is used to prevent compiler warnings. */
|
||||||
|
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||||
|
xStart.xBlockSize = ( size_t ) 0;
|
||||||
|
|
||||||
|
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||||
|
* at the end of the heap space. */
|
||||||
|
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||||
|
uxAddress -= xHeapStructSize;
|
||||||
|
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||||
|
pxEnd = ( void * ) uxAddress;
|
||||||
|
pxEnd->xBlockSize = 0;
|
||||||
|
pxEnd->pxNextFreeBlock = NULL;
|
||||||
|
|
||||||
|
/* To start with there is a single free block that is sized to take up the
|
||||||
|
* entire heap space, minus the space taken by pxEnd. */
|
||||||
|
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||||
|
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||||
|
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||||
|
|
||||||
|
/* Only one block exists - and it covers the entire usable heap space. */
|
||||||
|
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||||
|
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
|
||||||
|
{
|
||||||
|
BlockLink_t * pxIterator;
|
||||||
|
uint8_t * puc;
|
||||||
|
|
||||||
|
/* Iterate through the list until a block is found that has a higher address
|
||||||
|
* than the block being inserted. */
|
||||||
|
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||||
|
{
|
||||||
|
/* Nothing to do here, just iterate to the right position. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the block being inserted, and the block it is being inserted after
|
||||||
|
* make a contiguous block of memory? */
|
||||||
|
puc = ( uint8_t * ) pxIterator;
|
||||||
|
|
||||||
|
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||||
|
{
|
||||||
|
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||||
|
pxBlockToInsert = pxIterator;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the block being inserted, and the block it is being inserted before
|
||||||
|
* make a contiguous block of memory? */
|
||||||
|
puc = ( uint8_t * ) pxBlockToInsert;
|
||||||
|
|
||||||
|
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||||
|
{
|
||||||
|
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||||
|
{
|
||||||
|
/* Form one big block from the two blocks. */
|
||||||
|
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||||
|
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the block being inserted plugged a gap, so was merged with the block
|
||||||
|
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||||
|
* already been set, and should not be set here as that would make it point
|
||||||
|
* to itself. */
|
||||||
|
if( pxIterator != pxBlockToInsert )
|
||||||
|
{
|
||||||
|
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void * pvPortMalloc( size_t xWantedSize )
|
||||||
|
{
|
||||||
|
BlockLink_t * pxBlock;
|
||||||
|
BlockLink_t * pxPreviousBlock;
|
||||||
|
BlockLink_t * pxNewBlockLink;
|
||||||
|
void * pvReturn = NULL;
|
||||||
|
size_t xAdditionalRequiredSize;
|
||||||
|
size_t xAllocatedBlockSize = 0;
|
||||||
|
|
||||||
|
/* If this is the first call to malloc then the heap will require
|
||||||
|
* initialisation to setup the list of free blocks. */
|
||||||
|
if( pxEnd == NULL )
|
||||||
|
{
|
||||||
|
prvHeapInit();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xWantedSize > 0 )
|
||||||
|
{
|
||||||
|
/* The wanted size must be increased so it can contain a BlockLink_t
|
||||||
|
* structure in addition to the requested amount of bytes. */
|
||||||
|
if( secureheapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 )
|
||||||
|
{
|
||||||
|
xWantedSize += xHeapStructSize;
|
||||||
|
|
||||||
|
/* Ensure that blocks are always aligned to the required number
|
||||||
|
* of bytes. */
|
||||||
|
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||||
|
{
|
||||||
|
/* Byte alignment required. */
|
||||||
|
xAdditionalRequiredSize = secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK );
|
||||||
|
|
||||||
|
if( secureheapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 )
|
||||||
|
{
|
||||||
|
xWantedSize += xAdditionalRequiredSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xWantedSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xWantedSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the requested block size is not so large that the top bit is set.
|
||||||
|
* The top bit of the block size member of the BlockLink_t structure is used
|
||||||
|
* to determine who owns the block - the application or the kernel, so it
|
||||||
|
* must be free. */
|
||||||
|
if( secureheapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 )
|
||||||
|
{
|
||||||
|
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||||
|
{
|
||||||
|
/* Traverse the list from the start (lowest address) block until
|
||||||
|
* one of adequate size is found. */
|
||||||
|
pxPreviousBlock = &xStart;
|
||||||
|
pxBlock = xStart.pxNextFreeBlock;
|
||||||
|
|
||||||
|
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||||
|
{
|
||||||
|
pxPreviousBlock = pxBlock;
|
||||||
|
pxBlock = pxBlock->pxNextFreeBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the end marker was reached then a block of adequate size was
|
||||||
|
* not found. */
|
||||||
|
if( pxBlock != pxEnd )
|
||||||
|
{
|
||||||
|
/* Return the memory space pointed to - jumping over the
|
||||||
|
* BlockLink_t structure at its start. */
|
||||||
|
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||||
|
|
||||||
|
/* This block is being returned for use so must be taken out
|
||||||
|
* of the list of free blocks. */
|
||||||
|
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||||
|
|
||||||
|
/* If the block is larger than required it can be split into
|
||||||
|
* two. */
|
||||||
|
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||||
|
{
|
||||||
|
/* This block is to be split into two. Create a new
|
||||||
|
* block following the number of bytes requested. The void
|
||||||
|
* cast is used to prevent byte alignment warnings from the
|
||||||
|
* compiler. */
|
||||||
|
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||||
|
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||||
|
|
||||||
|
/* Calculate the sizes of two blocks split from the single
|
||||||
|
* block. */
|
||||||
|
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||||
|
pxBlock->xBlockSize = xWantedSize;
|
||||||
|
|
||||||
|
/* Insert the new block into the list of free blocks. */
|
||||||
|
pxNewBlockLink->pxNextFreeBlock = pxPreviousBlock->pxNextFreeBlock;
|
||||||
|
pxPreviousBlock->pxNextFreeBlock = pxNewBlockLink;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||||
|
|
||||||
|
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||||
|
{
|
||||||
|
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
xAllocatedBlockSize = pxBlock->xBlockSize;
|
||||||
|
|
||||||
|
/* The block is being returned - it is allocated and owned by
|
||||||
|
* the application and has no "next" block. */
|
||||||
|
secureheapALLOCATE_BLOCK( pxBlock );
|
||||||
|
pxBlock->pxNextFreeBlock = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
traceMALLOC( pvReturn, xAllocatedBlockSize );
|
||||||
|
|
||||||
|
/* Prevent compiler warnings when trace macros are not used. */
|
||||||
|
( void ) xAllocatedBlockSize;
|
||||||
|
|
||||||
|
#if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||||
|
{
|
||||||
|
if( pvReturn == NULL )
|
||||||
|
{
|
||||||
|
extern void vApplicationMallocFailedHook( void );
|
||||||
|
vApplicationMallocFailedHook();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||||
|
|
||||||
|
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||||
|
return pvReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortFree( void * pv )
|
||||||
|
{
|
||||||
|
uint8_t * puc = ( uint8_t * ) pv;
|
||||||
|
BlockLink_t * pxLink;
|
||||||
|
|
||||||
|
if( pv != NULL )
|
||||||
|
{
|
||||||
|
/* The memory being freed will have an BlockLink_t structure immediately
|
||||||
|
* before it. */
|
||||||
|
puc -= xHeapStructSize;
|
||||||
|
|
||||||
|
/* This casting is to keep the compiler from issuing warnings. */
|
||||||
|
pxLink = ( void * ) puc;
|
||||||
|
|
||||||
|
/* Check the block is actually allocated. */
|
||||||
|
secureportASSERT( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 );
|
||||||
|
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||||
|
|
||||||
|
if( secureheapBLOCK_IS_ALLOCATED( pxLink ) != 0 )
|
||||||
|
{
|
||||||
|
if( pxLink->pxNextFreeBlock == NULL )
|
||||||
|
{
|
||||||
|
/* The block is being returned to the heap - it is no longer
|
||||||
|
* allocated. */
|
||||||
|
secureheapFREE_BLOCK( pxLink );
|
||||||
|
|
||||||
|
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||||
|
{
|
||||||
|
/* Add this block to the list of free blocks. */
|
||||||
|
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||||
|
traceFREE( pv, pxLink->xBlockSize );
|
||||||
|
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||||
|
}
|
||||||
|
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
size_t xPortGetFreeHeapSize( void )
|
||||||
|
{
|
||||||
|
return xFreeBytesRemaining;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||||
|
{
|
||||||
|
return xMinimumEverFreeBytesRemaining;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SECURE_HEAP_H__
|
||||||
|
#define __SECURE_HEAP_H__
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocates memory from heap.
|
||||||
|
*
|
||||||
|
* @param[in] xWantedSize The size of the memory to be allocated.
|
||||||
|
*
|
||||||
|
* @return Pointer to the memory region if the allocation is successful, NULL
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
void * pvPortMalloc( size_t xWantedSize );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Frees the previously allocated memory.
|
||||||
|
*
|
||||||
|
* @param[in] pv Pointer to the memory to be freed.
|
||||||
|
*/
|
||||||
|
void vPortFree( void * pv );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the free heap size.
|
||||||
|
*
|
||||||
|
* @return Free heap size.
|
||||||
|
*/
|
||||||
|
size_t xPortGetFreeHeapSize( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the minimum ever free heap size.
|
||||||
|
*
|
||||||
|
* @return Minimum ever free heap size.
|
||||||
|
*/
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSize( void );
|
||||||
|
|
||||||
|
#endif /* __SECURE_HEAP_H__ */
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Secure init includes. */
|
||||||
|
#include "secure_init.h"
|
||||||
|
|
||||||
|
/* Secure port macros. */
|
||||||
|
#include "secure_port_macros.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constants required to manipulate the SCB.
|
||||||
|
*/
|
||||||
|
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||||
|
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||||
|
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||||
|
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||||
|
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constants required to manipulate the FPU.
|
||||||
|
*/
|
||||||
|
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||||
|
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||||
|
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||||
|
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||||
|
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||||
|
|
||||||
|
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||||
|
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||||
|
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||||
|
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||||
|
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
|
||||||
|
{
|
||||||
|
uint32_t ulIPSR;
|
||||||
|
|
||||||
|
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||||
|
secureportREAD_IPSR( ulIPSR );
|
||||||
|
|
||||||
|
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||||
|
* when the processor is running in the Thread Mode. */
|
||||||
|
if( ulIPSR != 0 )
|
||||||
|
{
|
||||||
|
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||||
|
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||||
|
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
|
||||||
|
{
|
||||||
|
uint32_t ulIPSR;
|
||||||
|
|
||||||
|
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||||
|
secureportREAD_IPSR( ulIPSR );
|
||||||
|
|
||||||
|
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||||
|
* when the processor is running in the Thread Mode. */
|
||||||
|
if( ulIPSR != 0 )
|
||||||
|
{
|
||||||
|
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||||
|
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||||
|
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||||
|
|
||||||
|
/* LSPENS = 0 ==> LSPEN is writable from non-secure state. This ensures
|
||||||
|
* that we can enable/disable lazy stacking in port.c file. */
|
||||||
|
*( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
|
||||||
|
|
||||||
|
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||||
|
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||||
|
* restored on exception return. */
|
||||||
|
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SECURE_INIT_H__
|
||||||
|
#define __SECURE_INIT_H__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief De-prioritizes the non-secure exceptions.
|
||||||
|
*
|
||||||
|
* This is needed to ensure that the non-secure PendSV runs at the lowest
|
||||||
|
* priority. Context switch is done in the non-secure PendSV handler.
|
||||||
|
*
|
||||||
|
* @note This function must be called in the handler mode. It is no-op if called
|
||||||
|
* in the thread mode.
|
||||||
|
*/
|
||||||
|
void SecureInit_DePrioritizeNSExceptions( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets up the Floating Point Unit (FPU) for Non-Secure access.
|
||||||
|
*
|
||||||
|
* Also sets FPCCR.TS=1 to ensure that the content of the Floating Point
|
||||||
|
* Registers are not leaked to the non-secure side.
|
||||||
|
*
|
||||||
|
* @note This function must be called in the handler mode. It is no-op if called
|
||||||
|
* in the thread mode.
|
||||||
|
*/
|
||||||
|
void SecureInit_EnableNSFPUAccess( void );
|
||||||
|
|
||||||
|
#endif /* __SECURE_INIT_H__ */
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SECURE_PORT_MACROS_H__
|
||||||
|
#define __SECURE_PORT_MACROS_H__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Byte alignment requirements.
|
||||||
|
*/
|
||||||
|
#define secureportBYTE_ALIGNMENT 8
|
||||||
|
#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Macro to declare a function as non-secure callable.
|
||||||
|
*/
|
||||||
|
#if defined( __IAR_SYSTEMS_ICC__ )
|
||||||
|
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
|
||||||
|
#else
|
||||||
|
#define secureportNON_SECURE_CALLABLE __attribute__( ( cmse_nonsecure_entry ) ) __attribute__( ( used ) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the secure PRIMASK value.
|
||||||
|
*/
|
||||||
|
#define secureportSET_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||||
|
__asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the non-secure PRIMASK value.
|
||||||
|
*/
|
||||||
|
#define secureportSET_NON_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||||
|
__asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read the PSP value in the given variable.
|
||||||
|
*/
|
||||||
|
#define secureportREAD_PSP( pucOutCurrentStackPointer ) \
|
||||||
|
__asm volatile ( "mrs %0, psp" : "=r" ( pucOutCurrentStackPointer ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the PSP to the given value.
|
||||||
|
*/
|
||||||
|
#define secureportSET_PSP( pucCurrentStackPointer ) \
|
||||||
|
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read the PSPLIM value in the given variable.
|
||||||
|
*/
|
||||||
|
#define secureportREAD_PSPLIM( pucOutStackLimit ) \
|
||||||
|
__asm volatile ( "mrs %0, psplim" : "=r" ( pucOutStackLimit ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the PSPLIM to the given value.
|
||||||
|
*/
|
||||||
|
#define secureportSET_PSPLIM( pucStackLimit ) \
|
||||||
|
__asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the NonSecure MSP to the given value.
|
||||||
|
*/
|
||||||
|
#define secureportSET_MSP_NS( pucMainStackPointer ) \
|
||||||
|
__asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the CONTROL register to the given value.
|
||||||
|
*/
|
||||||
|
#define secureportSET_CONTROL( ulControl ) \
|
||||||
|
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read the Interrupt Program Status Register (IPSR) value in the given
|
||||||
|
* variable.
|
||||||
|
*/
|
||||||
|
#define secureportREAD_IPSR( ulIPSR ) \
|
||||||
|
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PRIMASK value to enable interrupts.
|
||||||
|
*/
|
||||||
|
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PRIMASK value to disable interrupts.
|
||||||
|
*/
|
||||||
|
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable secure interrupts.
|
||||||
|
*/
|
||||||
|
#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable non-secure interrupts.
|
||||||
|
*
|
||||||
|
* This effectively disables context switches.
|
||||||
|
*/
|
||||||
|
#define secureportDISABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable non-secure interrupts.
|
||||||
|
*/
|
||||||
|
#define secureportENABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Assert definition.
|
||||||
|
*/
|
||||||
|
#define secureportASSERT( x ) \
|
||||||
|
if( ( x ) == 0 ) \
|
||||||
|
{ \
|
||||||
|
secureportDISABLE_SECURE_INTERRUPTS(); \
|
||||||
|
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
|
||||||
|
for( ; ; ) {; } \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __SECURE_PORT_MACROS_H__ */
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V1.00:
|
||||||
|
|
||||||
|
+ Call to taskYIELD() from within tick ISR has been replaced by the more
|
||||||
|
efficient portSWITCH_CONTEXT().
|
||||||
|
+ ISR function definitions renamed to include the prv prefix.
|
||||||
|
|
||||||
|
Changes from V2.6.1
|
||||||
|
|
||||||
|
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
|
||||||
|
macro to be consistent with the later ports.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Implementation of functions defined in portable.h for the Flashlite 186
|
||||||
|
* port.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <dos.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "portasm.h"
|
||||||
|
|
||||||
|
/*lint -e950 Non ANSI reserved words okay in this file only. */
|
||||||
|
|
||||||
|
#define portTIMER_EOI_TYPE ( 8 )
|
||||||
|
#define portRESET_PIC() portOUTPUT_WORD( ( uint16_t ) 0xff22, portTIMER_EOI_TYPE )
|
||||||
|
#define portTIMER_INT_NUMBER 0x12
|
||||||
|
|
||||||
|
#define portTIMER_1_CONTROL_REGISTER ( ( uint16_t ) 0xff5e )
|
||||||
|
#define portTIMER_0_CONTROL_REGISTER ( ( uint16_t ) 0xff56 )
|
||||||
|
#define portTIMER_INTERRUPT_ENABLE ( ( uint16_t ) 0x2000 )
|
||||||
|
|
||||||
|
/* Setup the hardware to generate the required tick frequency. */
|
||||||
|
static void prvSetTickFrequency( uint32_t ulTickRateHz );
|
||||||
|
|
||||||
|
/* Set the hardware back to the state as per before the scheduler started. */
|
||||||
|
static void prvExitFunction( void );
|
||||||
|
|
||||||
|
/* The ISR used depends on whether the preemptive or cooperative scheduler
|
||||||
|
is being used. */
|
||||||
|
#if( configUSE_PREEMPTION == 1 )
|
||||||
|
/* Tick service routine used by the scheduler when preemptive scheduling is
|
||||||
|
being used. */
|
||||||
|
static void __interrupt __far prvPreemptiveTick( void );
|
||||||
|
#else
|
||||||
|
/* Tick service routine used by the scheduler when cooperative scheduling is
|
||||||
|
being used. */
|
||||||
|
static void __interrupt __far prvNonPreemptiveTick( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Trap routine used by taskYIELD() to manually cause a context switch. */
|
||||||
|
static void __interrupt __far prvYieldProcessor( void );
|
||||||
|
|
||||||
|
/*lint -e956 File scopes necessary here. */
|
||||||
|
|
||||||
|
/* Set true when the vectors are set so the scheduler will service the tick. */
|
||||||
|
static BaseType_t xSchedulerRunning = pdFALSE;
|
||||||
|
|
||||||
|
/* Points to the original routine installed on the vector we use for manual
|
||||||
|
context switches. This is then used to restore the original routine during
|
||||||
|
prvExitFunction(). */
|
||||||
|
static void ( __interrupt __far *pxOldSwitchISR )();
|
||||||
|
|
||||||
|
/* Used to restore the original DOS context when the scheduler is ended. */
|
||||||
|
static jmp_buf xJumpBuf;
|
||||||
|
|
||||||
|
/*lint +e956 */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
/* This is called with interrupts already disabled. */
|
||||||
|
|
||||||
|
/* Remember what was on the interrupts we are going to use
|
||||||
|
so we can put them back later if required. */
|
||||||
|
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
|
||||||
|
|
||||||
|
/* Put our manual switch (yield) function on a known
|
||||||
|
vector. */
|
||||||
|
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
|
||||||
|
|
||||||
|
#if( configUSE_PREEMPTION == 1 )
|
||||||
|
{
|
||||||
|
/* Put our tick switch function on the timer interrupt. */
|
||||||
|
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
/* We want the timer interrupt to just increment the tick count. */
|
||||||
|
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
prvSetTickFrequency( configTICK_RATE_HZ );
|
||||||
|
|
||||||
|
/* Clean up function if we want to return to DOS. */
|
||||||
|
if( setjmp( xJumpBuf ) != 0 )
|
||||||
|
{
|
||||||
|
prvExitFunction();
|
||||||
|
xSchedulerRunning = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xSchedulerRunning = pdTRUE;
|
||||||
|
|
||||||
|
/* Kick off the scheduler by setting up the context of the first task. */
|
||||||
|
portFIRST_CONTEXT();
|
||||||
|
}
|
||||||
|
|
||||||
|
return xSchedulerRunning;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* The ISR used depends on whether the preemptive or cooperative scheduler
|
||||||
|
is being used. */
|
||||||
|
#if( configUSE_PREEMPTION == 1 )
|
||||||
|
static void __interrupt __far prvPreemptiveTick( void )
|
||||||
|
{
|
||||||
|
/* Get the scheduler to update the task states following the tick. */
|
||||||
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
|
{
|
||||||
|
/* Switch in the context of the next task to be run. */
|
||||||
|
portSWITCH_CONTEXT();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the PIC ready for the next time. */
|
||||||
|
portRESET_PIC();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void __interrupt __far prvNonPreemptiveTick( void )
|
||||||
|
{
|
||||||
|
/* Same as preemptive tick, but the cooperative scheduler is being used
|
||||||
|
so we don't have to switch in the context of the next task. */
|
||||||
|
xTaskIncrementTick();
|
||||||
|
portRESET_PIC();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void __interrupt __far prvYieldProcessor( void )
|
||||||
|
{
|
||||||
|
/* Switch in the context of the next task to be run. */
|
||||||
|
portSWITCH_CONTEXT();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEndScheduler( void )
|
||||||
|
{
|
||||||
|
/* Jump back to the processor state prior to starting the
|
||||||
|
scheduler. This means we are not going to be using a
|
||||||
|
task stack frame so the task can be deleted. */
|
||||||
|
longjmp( xJumpBuf, 1 );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvExitFunction( void )
|
||||||
|
{
|
||||||
|
const uint16_t usTimerDisable = 0x0000;
|
||||||
|
uint16_t usTimer0Control;
|
||||||
|
|
||||||
|
/* Interrupts should be disabled here anyway - but no
|
||||||
|
harm in making sure. */
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
if( xSchedulerRunning == pdTRUE )
|
||||||
|
{
|
||||||
|
/* Put back the switch interrupt routines that was in place
|
||||||
|
before the scheduler started. */
|
||||||
|
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable the timer used for the tick to ensure the scheduler is
|
||||||
|
not called before restoring interrupts. There was previously nothing
|
||||||
|
on this timer so there is no old ISR to restore. */
|
||||||
|
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable );
|
||||||
|
|
||||||
|
/* Restart the DOS tick. */
|
||||||
|
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
|
||||||
|
usTimer0Control |= portTIMER_INTERRUPT_ENABLE;
|
||||||
|
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
|
||||||
|
|
||||||
|
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSetTickFrequency( uint32_t ulTickRateHz )
|
||||||
|
{
|
||||||
|
const uint16_t usMaxCountRegister = 0xff5a;
|
||||||
|
const uint16_t usTimerPriorityRegister = 0xff32;
|
||||||
|
const uint16_t usTimerEnable = 0xC000;
|
||||||
|
const uint16_t usRetrigger = 0x0001;
|
||||||
|
const uint16_t usTimerHighPriority = 0x0000;
|
||||||
|
uint16_t usTimer0Control;
|
||||||
|
|
||||||
|
/* ( CPU frequency / 4 ) / clock 2 max count [inpw( 0xff62 ) = 7] */
|
||||||
|
|
||||||
|
const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL;
|
||||||
|
|
||||||
|
uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz;
|
||||||
|
|
||||||
|
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger );
|
||||||
|
portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount );
|
||||||
|
portOUTPUT_WORD( usTimerPriorityRegister, usTimerHighPriority );
|
||||||
|
|
||||||
|
/* Stop the DOS tick - don't do this if you want to maintain a TOD clock. */
|
||||||
|
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
|
||||||
|
usTimer0Control &= ~portTIMER_INTERRUPT_ENABLE;
|
||||||
|
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*lint +e950 */
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE long
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT int
|
||||||
|
#define portSTACK_TYPE uint16_t
|
||||||
|
#define portBASE_TYPE portSHORT
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef short BaseType_t;
|
||||||
|
typedef unsigned short UBaseType_t;
|
||||||
|
|
||||||
|
#if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
#else
|
||||||
|
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Critical section handling. */
|
||||||
|
#define portENTER_CRITICAL() __asm{ pushf } \
|
||||||
|
__asm{ cli } \
|
||||||
|
|
||||||
|
#define portEXIT_CRITICAL() __asm{ popf }
|
||||||
|
|
||||||
|
#define portDISABLE_INTERRUPTS() __asm{ cli }
|
||||||
|
|
||||||
|
#define portENABLE_INTERRUPTS() __asm{ sti }
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Hardware specifics. */
|
||||||
|
#define portNOP() __asm{ nop }
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portSWITCH_INT_NUMBER 0x80
|
||||||
|
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 2
|
||||||
|
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Compiler specifics. */
|
||||||
|
#define portINPUT_BYTE( xAddr ) inp( xAddr )
|
||||||
|
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
|
||||||
|
#define portINPUT_WORD( xAddr ) inpw( xAddr )
|
||||||
|
#define portOUTPUT_WORD( xAddr, usValue ) outpw( xAddr, usValue )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||||
|
#define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
@@ -0,0 +1,288 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V2.6.1
|
||||||
|
|
||||||
|
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
|
||||||
|
macro to be consistent with the later ports.
|
||||||
|
|
||||||
|
Changes from V4.0.1
|
||||||
|
|
||||||
|
+ Add function prvSetTickFrequencyDefault() to set the DOS tick back to
|
||||||
|
its proper value when the scheduler exits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "portasm.h"
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Implementation of functions defined in portable.h for the industrial
|
||||||
|
* PC port.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*lint -e950 Non ANSI reserved words okay in this file only. */
|
||||||
|
|
||||||
|
#define portTIMER_INT_NUMBER 0x08
|
||||||
|
|
||||||
|
/* Setup hardware for required tick interrupt rate. */
|
||||||
|
static void prvSetTickFrequency( uint32_t ulTickRateHz );
|
||||||
|
|
||||||
|
/* Restore hardware to as it was prior to starting the scheduler. */
|
||||||
|
static void prvExitFunction( void );
|
||||||
|
|
||||||
|
/* Either chain to the DOS tick (which itself clears the PIC) or clear the PIC
|
||||||
|
directly. We chain to the DOS tick as close as possible to the standard DOS
|
||||||
|
tick rate. */
|
||||||
|
static void prvPortResetPIC( void );
|
||||||
|
|
||||||
|
/* The ISR used depends on whether the preemptive or cooperative
|
||||||
|
scheduler is being used. */
|
||||||
|
#if( configUSE_PREEMPTION == 1 )
|
||||||
|
/* Tick service routine used by the scheduler when preemptive scheduling is
|
||||||
|
being used. */
|
||||||
|
static void __interrupt __far prvPreemptiveTick( void );
|
||||||
|
#else
|
||||||
|
/* Tick service routine used by the scheduler when cooperative scheduling is
|
||||||
|
being used. */
|
||||||
|
static void __interrupt __far prvNonPreemptiveTick( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Trap routine used by taskYIELD() to manually cause a context switch. */
|
||||||
|
static void __interrupt __far prvYieldProcessor( void );
|
||||||
|
|
||||||
|
/* Set the tick frequency back so the floppy drive works correctly when the
|
||||||
|
scheduler exits. */
|
||||||
|
static void prvSetTickFrequencyDefault( void );
|
||||||
|
|
||||||
|
/*lint -e956 File scopes necessary here. */
|
||||||
|
|
||||||
|
/* Used to signal when to chain to the DOS tick, and when to just clear the PIC ourselves. */
|
||||||
|
static int16_t sDOSTickCounter;
|
||||||
|
|
||||||
|
/* Set true when the vectors are set so the scheduler will service the tick. */
|
||||||
|
static BaseType_t xSchedulerRunning = pdFALSE;
|
||||||
|
|
||||||
|
/* Points to the original routine installed on the vector we use for manual context switches. This is then used to restore the original routine during prvExitFunction(). */
|
||||||
|
static void ( __interrupt __far *pxOldSwitchISR )();
|
||||||
|
|
||||||
|
/* Points to the original routine installed on the vector we use to chain to the DOS tick. This is then used to restore the original routine during prvExitFunction(). */
|
||||||
|
static void ( __interrupt __far *pxOldSwitchISRPlus1 )();
|
||||||
|
|
||||||
|
/* Used to restore the original DOS context when the scheduler is ended. */
|
||||||
|
static jmp_buf xJumpBuf;
|
||||||
|
|
||||||
|
/*lint +e956 */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
pxISR pxOriginalTickISR;
|
||||||
|
|
||||||
|
/* This is called with interrupts already disabled. */
|
||||||
|
|
||||||
|
/* Remember what was on the interrupts we are going to use
|
||||||
|
so we can put them back later if required. */
|
||||||
|
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
|
||||||
|
pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER );
|
||||||
|
pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
|
||||||
|
|
||||||
|
prvSetTickFrequency( configTICK_RATE_HZ );
|
||||||
|
|
||||||
|
/* Put our manual switch (yield) function on a known
|
||||||
|
vector. */
|
||||||
|
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
|
||||||
|
|
||||||
|
/* Put the old tick on a different interrupt number so we can
|
||||||
|
call it when we want. */
|
||||||
|
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR );
|
||||||
|
|
||||||
|
/* The ISR used depends on whether the preemptive or cooperative
|
||||||
|
scheduler is being used. */
|
||||||
|
#if( configUSE_PREEMPTION == 1 )
|
||||||
|
{
|
||||||
|
/* Put our tick switch function on the timer interrupt. */
|
||||||
|
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
/* We want the timer interrupt to just increment the tick count. */
|
||||||
|
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Setup a counter that is used to call the DOS interrupt as close
|
||||||
|
to it's original frequency as can be achieved given our chosen tick
|
||||||
|
frequency. */
|
||||||
|
sDOSTickCounter = portTICKS_PER_DOS_TICK;
|
||||||
|
|
||||||
|
/* Clean up function if we want to return to DOS. */
|
||||||
|
if( setjmp( xJumpBuf ) != 0 )
|
||||||
|
{
|
||||||
|
prvExitFunction();
|
||||||
|
xSchedulerRunning = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xSchedulerRunning = pdTRUE;
|
||||||
|
|
||||||
|
/* Kick off the scheduler by setting up the context of the first task. */
|
||||||
|
portFIRST_CONTEXT();
|
||||||
|
}
|
||||||
|
|
||||||
|
return xSchedulerRunning;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* The ISR used depends on whether the preemptive or cooperative
|
||||||
|
scheduler is being used. */
|
||||||
|
#if( configUSE_PREEMPTION == 1 )
|
||||||
|
static void __interrupt __far prvPreemptiveTick( void )
|
||||||
|
{
|
||||||
|
/* Get the scheduler to update the task states following the tick. */
|
||||||
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
|
{
|
||||||
|
/* Switch in the context of the next task to be run. */
|
||||||
|
portSWITCH_CONTEXT();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the PIC ready for the next time. */
|
||||||
|
prvPortResetPIC();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void __interrupt __far prvNonPreemptiveTick( void )
|
||||||
|
{
|
||||||
|
/* Same as preemptive tick, but the cooperative scheduler is being used
|
||||||
|
so we don't have to switch in the context of the next task. */
|
||||||
|
xTaskIncrementTick();
|
||||||
|
prvPortResetPIC();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void __interrupt __far prvYieldProcessor( void )
|
||||||
|
{
|
||||||
|
/* Switch in the context of the next task to be run. */
|
||||||
|
portSWITCH_CONTEXT();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvPortResetPIC( void )
|
||||||
|
{
|
||||||
|
/* We are going to call the DOS tick interrupt at as close a
|
||||||
|
frequency to the normal DOS tick as possible. */
|
||||||
|
|
||||||
|
/* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */
|
||||||
|
--sDOSTickCounter;
|
||||||
|
if( sDOSTickCounter <= 0 )
|
||||||
|
{
|
||||||
|
sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK;
|
||||||
|
__asm{ int portSWITCH_INT_NUMBER + 1 };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Reset the PIC as the DOS tick is not being called to
|
||||||
|
do it. */
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov al, 20H
|
||||||
|
out 20H, al
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEndScheduler( void )
|
||||||
|
{
|
||||||
|
/* Jump back to the processor state prior to starting the
|
||||||
|
scheduler. This means we are not going to be using a
|
||||||
|
task stack frame so the task can be deleted. */
|
||||||
|
longjmp( xJumpBuf, 1 );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvExitFunction( void )
|
||||||
|
{
|
||||||
|
void ( __interrupt __far *pxOriginalTickISR )();
|
||||||
|
|
||||||
|
/* Interrupts should be disabled here anyway - but no
|
||||||
|
harm in making sure. */
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
if( xSchedulerRunning == pdTRUE )
|
||||||
|
{
|
||||||
|
/* Set the DOS tick back onto the timer ticker. */
|
||||||
|
pxOriginalTickISR = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
|
||||||
|
_dos_setvect( portTIMER_INT_NUMBER, pxOriginalTickISR );
|
||||||
|
prvSetTickFrequencyDefault();
|
||||||
|
|
||||||
|
/* Put back the switch interrupt routines that was in place
|
||||||
|
before the scheduler started. */
|
||||||
|
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
|
||||||
|
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 );
|
||||||
|
}
|
||||||
|
/* The tick timer is back how DOS wants it. We can re-enable
|
||||||
|
interrupts without the scheduler being called. */
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSetTickFrequency( uint32_t ulTickRateHz )
|
||||||
|
{
|
||||||
|
const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
|
||||||
|
const uint16_t usPIT0 = ( uint16_t ) 0x40;
|
||||||
|
const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL;
|
||||||
|
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
|
||||||
|
uint32_t ulOutput;
|
||||||
|
|
||||||
|
/* Setup the 8245 to tick at the wanted frequency. */
|
||||||
|
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
|
||||||
|
ulOutput = ulPIT_CONST / ulTickRateHz;
|
||||||
|
portOUTPUT_BYTE( usPIT0, ( uint16_t )( ulOutput & ( uint32_t ) 0xff ) );
|
||||||
|
ulOutput >>= 8;
|
||||||
|
portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSetTickFrequencyDefault( void )
|
||||||
|
{
|
||||||
|
const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
|
||||||
|
const uint16_t usPIT0 = ( uint16_t ) 0x40;
|
||||||
|
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
|
||||||
|
|
||||||
|
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
|
||||||
|
portOUTPUT_BYTE( usPIT0,0 );
|
||||||
|
portOUTPUT_BYTE( usPIT0,0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*lint +e950 */
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT long
|
||||||
|
#define portDOUBLE long
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT int
|
||||||
|
#define portSTACK_TYPE uint16_t
|
||||||
|
#define portBASE_TYPE portSHORT
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef short BaseType_t;
|
||||||
|
typedef unsigned short UBaseType_t;
|
||||||
|
|
||||||
|
#if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
#else
|
||||||
|
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
#define portENTER_CRITICAL() __asm{ pushf } \
|
||||||
|
__asm{ cli } \
|
||||||
|
|
||||||
|
#define portEXIT_CRITICAL() __asm{ popf }
|
||||||
|
|
||||||
|
#define portDISABLE_INTERRUPTS() __asm{ cli }
|
||||||
|
|
||||||
|
#define portENABLE_INTERRUPTS() __asm{ sti }
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Hardware specifics. */
|
||||||
|
#define portNOP() __asm{ nop }
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portSWITCH_INT_NUMBER 0x80
|
||||||
|
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
|
||||||
|
#define portDOS_TICK_RATE ( 18.20648 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portTICKS_PER_DOS_TICK ( ( uint16_t ) ( ( ( portDOUBLE ) configTICK_RATE_HZ / portDOS_TICK_RATE ) + 0.5 ) )
|
||||||
|
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
|
||||||
|
#define portBYTE_ALIGNMENT ( 2 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Compiler specifics. */
|
||||||
|
#define portINPUT_BYTE( xAddr ) inp( xAddr )
|
||||||
|
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||||
|
#define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORT_ASM_H
|
||||||
|
#define PORT_ASM_H
|
||||||
|
|
||||||
|
typedef void TCB_t;
|
||||||
|
extern volatile TCB_t * volatile pxCurrentTCB;
|
||||||
|
extern void vTaskSwitchContext( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Saves the stack pointer for one task into its TCB, calls
|
||||||
|
* vTaskSwitchContext() to update the TCB being used, then restores the stack
|
||||||
|
* from the new TCB read to run the task.
|
||||||
|
*/
|
||||||
|
void portSWITCH_CONTEXT( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load the stack pointer from the TCB of the task which is going to be first
|
||||||
|
* to execute. Then force an IRET so the registers and IP are popped off the
|
||||||
|
* stack.
|
||||||
|
*/
|
||||||
|
void portFIRST_CONTEXT( void );
|
||||||
|
|
||||||
|
/* There are slightly different versions depending on whether you are building
|
||||||
|
to include debugger information. If debugger information is used then there
|
||||||
|
are a couple of extra bytes left of the ISR stack (presumably for use by the
|
||||||
|
debugger). The true stack pointer is then stored in the bp register. We add
|
||||||
|
2 to the stack pointer to remove the extra bytes before we restore our context. */
|
||||||
|
|
||||||
|
#define portSWITCH_CONTEXT() \
|
||||||
|
asm { mov ax, seg pxCurrentTCB } \
|
||||||
|
asm { mov ds, ax } \
|
||||||
|
asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \
|
||||||
|
asm { mov es:0x2[ bx ], ss } \
|
||||||
|
asm { mov es:[ bx ], sp } \
|
||||||
|
asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \
|
||||||
|
asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \
|
||||||
|
asm { mov ds, ax } \
|
||||||
|
asm { les bx, dword ptr pxCurrentTCB } \
|
||||||
|
asm { mov ss, es:[ bx + 2 ] } \
|
||||||
|
asm { mov sp, es:[ bx ] }
|
||||||
|
|
||||||
|
#define portFIRST_CONTEXT() \
|
||||||
|
__asm { mov ax, seg pxCurrentTCB } \
|
||||||
|
__asm { mov ds, ax } \
|
||||||
|
__asm { les bx, dword ptr pxCurrentTCB } \
|
||||||
|
__asm { mov ss, es:[ bx + 2 ] } \
|
||||||
|
__asm { mov sp, es:[ bx ] } \
|
||||||
|
__asm { pop bp } \
|
||||||
|
__asm { pop di } \
|
||||||
|
__asm { pop si } \
|
||||||
|
__asm { pop ds } \
|
||||||
|
__asm { pop es } \
|
||||||
|
__asm { pop dx } \
|
||||||
|
__asm { pop cx } \
|
||||||
|
__asm { pop bx } \
|
||||||
|
__asm { pop ax } \
|
||||||
|
__asm { iret }
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V1.00:
|
||||||
|
|
||||||
|
+ pxPortInitialiseStack() now initialises the stack of new tasks to the
|
||||||
|
same format used by the compiler. This allows the compiler generated
|
||||||
|
interrupt mechanism to be used for context switches.
|
||||||
|
|
||||||
|
Changes from V2.6.1
|
||||||
|
|
||||||
|
+ Move usPortCheckFreeStackSpace() to tasks.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <dos.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* See header file for description. */
|
||||||
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||||
|
{
|
||||||
|
StackType_t DS_Reg = 0;
|
||||||
|
|
||||||
|
/* Place a few bytes of known values on the bottom of the stack.
|
||||||
|
This is just useful for debugging. */
|
||||||
|
|
||||||
|
*pxTopOfStack = 0x1111;
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = 0x2222;
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = 0x3333;
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = 0x4444;
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = 0x5555;
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
|
||||||
|
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
|
||||||
|
|
||||||
|
/* We are going to start the scheduler using a return from interrupt
|
||||||
|
instruction to load the program counter, so first there would be the
|
||||||
|
function call with parameters preamble. */
|
||||||
|
|
||||||
|
*pxTopOfStack = FP_SEG( pvParameters );
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = FP_OFF( pvParameters );
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = FP_SEG( pxCode );
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = FP_OFF( pxCode );
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
/* Next the status register and interrupt return address. */
|
||||||
|
*pxTopOfStack = portINITIAL_SW;
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = FP_SEG( pxCode );
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = FP_OFF( pxCode );
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
/* The remaining registers would be pushed on the stack by our context
|
||||||
|
switch function. These are loaded with values simply to make debugging
|
||||||
|
easier. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
/* We need the true data segment. */
|
||||||
|
__asm{ MOV DS_Reg, DS };
|
||||||
|
|
||||||
|
*pxTopOfStack = DS_Reg; /* DS */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x0123; /* SI */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */
|
||||||
|
|
||||||
|
/*lint +e950 +e611 +e923 */
|
||||||
|
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# RH850/F1K and F1Kx FreeRTOS Port with CC-RH Compiler
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This repository contains the port of FreeRTOS for Renesas RH850/F1K and F1Kx microcontrollers using the CC-RH compiler. The following sections provide instructions on how to use this port, a link to the test project, and other relevant information.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
- Compiler: CC-RH
|
||||||
|
- FreeRTOS version 11.1.0
|
||||||
|
|
||||||
|
| Device | FPU | SMP |
|
||||||
|
|----------|-----|-----|
|
||||||
|
| F1K | Yes | No |
|
||||||
|
| F1KM-S1 | Yes | No |
|
||||||
|
| F1KM-S2 | Yes | No |
|
||||||
|
| F1KM-S4 | Yes | No |
|
||||||
|
| F1KH-D8 | Yes | Yes |
|
||||||
|
|
||||||
|
## Link to Test Project
|
||||||
|
|
||||||
|
The test project can be found [here](https://github.com/FreeRTOS/FreeRTOS-Community-Supported-Demos) (`RH850_F1Kx_CCRH`). This project contains example tasks and configurations to help you get started with FreeRTOS on the RH850/F1K and F1Kx.
|
||||||
|
|
||||||
|
## Note
|
||||||
|
1. Configure IPIR Interrupt: Ensure that the bit specifying the destination for binding (requesting) an interrupt is enabled (e.g: IBDxxx register of F1KH-D8) (1)
|
||||||
|
2. `Channel 0` and address `0xFFFEEC00` are used as default configuration for configIPIR_CHANNEL and configEXCLUSIVE_ADDRESS, in case of resource confliction other channel/address can be used. (2)
|
||||||
|
3. The minimal stack size (configMINIMAL_STACK_SIZE) must be included the reserved memory for nested interrupt. This formula can be referred: `(task_context_size) * (2 + configMAX_INT_NESTING) + Stack_depth_of_taskcode`
|
||||||
|
In which, `task_context_size` is calculated as `36*4bytes = 144bytes` (when FPU enabled) or `34*4bytes = 136` (when FPU disabled), configMAX_INT_NESTING is `02` as default (Note that a value of `0` is not allowed).
|
||||||
|
4. `configTIMER_PRESCALE`: This value is required in order to correctly configure clock for `CPUCLK_L`. Refer to Hardware Manual at `Table 44.22` for `option byte`: If the user sets the option byte `CKDIVMD to 1`, then `configTIMER_PRESCALE = 4`. Otherwise, if `CKDIVMD is set to 0`, then `configTIMER_PRESCALE = 2`.
|
||||||
|
|
||||||
|
(1) This is applicable for F1KH-D8 with SMP only.
|
||||||
|
|
||||||
|
(2) This is optional and applicable for SMP only.
|
||||||
|
|
||||||
|
## Other Relevant Information
|
||||||
|
|
||||||
|
- **Documentation:**
|
||||||
|
- Refer to the official [FreeRTOS documentation](https://www.freertos.org/Documentation/RTOS_book.html) for detailed information on configuring and using FreeRTOS.
|
||||||
|
- Consult the [RH850 F1K group user manual hardware manual](https://www.renesas.com/us/en/document/mah/rh850f1k-group-users-manual-hardware?r=1170166) for specific details about the microcontroller.
|
||||||
|
- For more information about Renesas RH850/F1K and F1Kx, please visit [this website](https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rh850-automotive-mcus)
|
||||||
|
- The CC-RH compiler can be downloaded [here](https://www.renesas.com/us/en/software-tool/c-compiler-package-rh850-family#downloads)
|
||||||
|
|
||||||
|
- **Support:**
|
||||||
|
- If you encounter any issues or have questions about this port, please open an issue in this repository or contact the maintainer.
|
||||||
|
|
||||||
|
- **Contributing:**
|
||||||
|
- Contributions to improve this port are welcome. Please fork the repository, make your changes, and submit a pull request.
|
||||||
@@ -0,0 +1,732 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* This port uses xTaskGetCurrentTaskHandle to get TCB stack, it is required to
|
||||||
|
* enable this API. */
|
||||||
|
#if ( ( INCLUDE_xTaskGetCurrentTaskHandle != 1 ) && ( configNUMBER_OF_CORES == 1 ) )
|
||||||
|
#error INCLUDE_xTaskGetCurrentTaskHandle must be set to 1 in single core.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Macro definitions
|
||||||
|
***********************************************************/
|
||||||
|
|
||||||
|
/* Hardware specific macros */
|
||||||
|
#define portPSW_REGISTER_ID ( 5 )
|
||||||
|
#define portFPSR_REGISTER_ID ( 6 )
|
||||||
|
|
||||||
|
/* PSW.EBV and PSW.CUx bits are kept as current status */
|
||||||
|
#define portINITIAL_PSW_MASK ( 0x000f8000 )
|
||||||
|
#define portCURRENT_PSW_VALUE ( portSTSR( portPSW_REGISTER_ID ) )
|
||||||
|
#define portCURRENT_SR_ZERO_VALUE ( ( StackType_t ) 0x00000000 )
|
||||||
|
#define portCURRENT_FPSR_VALUE ( portSTSR( portFPSR_REGISTER_ID ) )
|
||||||
|
|
||||||
|
/* Mask for FPU configuration bits (FN, PEM, RM, FS) */
|
||||||
|
#define portINITIAL_FPSR_MASK ( 0x00ae0000 )
|
||||||
|
#define portPSW_ID_MASK ( 0x00000020 )
|
||||||
|
|
||||||
|
/* Define necessary hardware IO for OSTM timer. OSTM0 is used by default as
|
||||||
|
* it is common for almost device variants. If it conflicts with application,
|
||||||
|
* the application shall implement another timer.*/
|
||||||
|
#define portOSTM_EIC_ADDR ( 0xFFFFB0A8 )
|
||||||
|
#define portOSTM0CMP_ADDR ( 0xFFD70000 )
|
||||||
|
#define portOSTM0CTL_ADDR ( 0xFFD70020 )
|
||||||
|
#define portOSTM0TS_ADDR ( 0xFFD70014 )
|
||||||
|
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
|
||||||
|
/* IPIR base address, the peripheral is used for Inter-Processor communication
|
||||||
|
* Hardware supports 4 channels which is offset by 0x0, 0x4, 0x8, 0xC bytes from
|
||||||
|
* base address. By default, channel 0 is selected. */
|
||||||
|
#ifdef configIPIR_CHANNEL
|
||||||
|
#define portIPIR_BASE_ADDR ( ( 0xFFFEEC80 ) + ( configIPIR_CHANNEL << 2 ) )
|
||||||
|
#else
|
||||||
|
#define portIPIR_BASE_ADDR ( 0xFFFEEC80 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Address used for exclusive control for variable shared between PEs
|
||||||
|
* (common resources), each CPU cores have independent access path to
|
||||||
|
* this address. By default, G0MEV0 register is selected*/
|
||||||
|
#ifdef configEXCLUSIVE_ADDRESS
|
||||||
|
#define portMEV_BASE_ADDR configEXCLUSIVE_ADDRESS
|
||||||
|
#else
|
||||||
|
#define portMEV_BASE_ADDR ( 0xFFFEEC00 )
|
||||||
|
#endif
|
||||||
|
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
|
||||||
|
|
||||||
|
/* Macros required to set up the initial stack. */
|
||||||
|
#define portSTACK_INITIAL_VALUE_R1 ( ( StackType_t ) 0x01010101 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R2 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x02 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R3 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x03 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R4 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x04 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R5 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x05 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R6 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x06 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R7 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x07 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R8 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x08 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R9 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x09 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R10 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x10 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R11 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x11 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R12 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x12 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R13 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x13 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R14 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x14 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R15 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x15 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R16 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x16 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R17 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x17 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R18 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x18 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R19 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x19 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R20 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x20 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R21 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x21 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R22 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x22 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R23 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x23 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R24 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x24 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R25 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x25 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R26 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x26 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R27 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x27 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R28 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x28 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R29 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x29 )
|
||||||
|
#define portSTACK_INITIAL_VALUE_R30 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x30 )
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* Typedef definitions
|
||||||
|
***********************************************************/
|
||||||
|
|
||||||
|
/* OSTM Count Start Trigger Register (OSTMnTS) */
|
||||||
|
#define portOSTM_COUNTER_START ( 0x01U ) /* Starts the counter */
|
||||||
|
|
||||||
|
/* OSTM Count Stop Trigger Register (OSTMnTT) */
|
||||||
|
#define portOSTM_COUNTER_STOP ( 0x01U ) /* Stops the counter */
|
||||||
|
|
||||||
|
/* OSTM Control Register (OSTMnCTL) */
|
||||||
|
#define portOSTM_MODE_INTERVAL_TIMER ( 0x00U )
|
||||||
|
#define portOSTM_MODE_FREE_RUNNING ( 0x02U )
|
||||||
|
|
||||||
|
/* Disables or Enable the interrupts when counting starts */
|
||||||
|
#define portOSTM_START_INTERRUPT_DISABLE ( 0x00U )
|
||||||
|
#define portOSTM_START_INTERRUPT_ENABLE ( 0x01U )
|
||||||
|
|
||||||
|
/* Interrupt vector method select (TBxxx) */
|
||||||
|
#define portINT_DIRECT_VECTOR ( 0x0U )
|
||||||
|
#define portINT_TABLE_VECTOR ( 0x1U )
|
||||||
|
|
||||||
|
/* Interrupt mask (MKxxx) */
|
||||||
|
#define portINT_PROCESSING_ENABLED ( 0x0U )
|
||||||
|
#define portINT_PROCESSING_DISABLED ( 0x1U )
|
||||||
|
|
||||||
|
/* Specify 16 interrupt priority levels */
|
||||||
|
#define portINT_PRIORITY_HIGHEST ( 0x0000U ) /* Level 0 (highest) */
|
||||||
|
#define portINT_PRIORITY_LEVEL1 ( 0x0001U ) /* Level 1 */
|
||||||
|
#define portINT_PRIORITY_LEVEL2 ( 0x0002U ) /* Level 2 */
|
||||||
|
#define portINT_PRIORITY_LEVEL3 ( 0x0003U ) /* Level 3 */
|
||||||
|
#define portINT_PRIORITY_LEVEL4 ( 0x0004U ) /* Level 4 */
|
||||||
|
#define portINT_PRIORITY_LEVEL5 ( 0x0005U ) /* Level 5 */
|
||||||
|
#define portINT_PRIORITY_LEVEL6 ( 0x0006U ) /* Level 6 */
|
||||||
|
#define portINT_PRIORITY_LEVEL7 ( 0x0007U ) /* Level 7 */
|
||||||
|
#define portINT_PRIORITY_LEVEL8 ( 0x0008U ) /* Level 8 */
|
||||||
|
#define portINT_PRIORITY_LEVEL9 ( 0x0009U ) /* Level 9 */
|
||||||
|
#define portINT_PRIORITY_LEVEL10 ( 0x000AU ) /* Level 10 */
|
||||||
|
#define portINT_PRIORITY_LEVEL11 ( 0x000BU ) /* Level 11 */
|
||||||
|
#define portINT_PRIORITY_LEVEL12 ( 0x000CU ) /* Level 12 */
|
||||||
|
#define portINT_PRIORITY_LEVEL13 ( 0x000DU ) /* Level 13 */
|
||||||
|
#define portINT_PRIORITY_LEVEL14 ( 0x000EU ) /* Level 14 */
|
||||||
|
#define portINT_PRIORITY_LOWEST ( 0x000FU ) /* Level 15 (lowest) */
|
||||||
|
|
||||||
|
/* Macros indicating status of scheduler request */
|
||||||
|
#define PORT_SCHEDULER_NOREQUEST 0UL
|
||||||
|
#define PORT_SCHEDULER_TASKSWITCH 1UL /* Do not modify */
|
||||||
|
#define PORT_SCHEDULER_STARTFIRSTTASK 2UL /* Do not modify */
|
||||||
|
|
||||||
|
#ifndef configSETUP_TICK_INTERRUPT
|
||||||
|
|
||||||
|
/* The user has not provided their own tick interrupt configuration so use
|
||||||
|
* the definition in this file (which uses the interval timer). */
|
||||||
|
#define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt()
|
||||||
|
#endif /* configSETUP_TICK_INTERRUPT */
|
||||||
|
|
||||||
|
#if ( !defined( configMAX_INT_NESTING ) || ( configMAX_INT_NESTING == 0 ) )
|
||||||
|
|
||||||
|
/* Set the default value for depth of nested interrupt. In theory, the
|
||||||
|
* microcontroller have mechanism to limit number of nested level of interrupt
|
||||||
|
* by priority (maximum 16 levels). However, the large stack memory should be
|
||||||
|
* prepared for each task to save resource in interrupt handler. Therefore, it
|
||||||
|
* is necessary to limit depth of nesting interrupt to optimize memory usage.
|
||||||
|
* In addition, the execution time of interrupt handler should be very short
|
||||||
|
* (typically not exceed 20us), this constraint does not impact to system.
|
||||||
|
*/
|
||||||
|
#define configMAX_INT_NESTING 2UL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to catch tasks that attempt to return from their implementing function.
|
||||||
|
*/
|
||||||
|
static void prvTaskExitError( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets up the periodic ISR used for the RTOS tick using the OSTM.
|
||||||
|
* The application writer can define configSETUP_TICK_INTERRUPT() (in
|
||||||
|
* FreeRTOSConfig.h) such that their own tick interrupt configuration is used
|
||||||
|
* in place of prvSetupTimerInterrupt().
|
||||||
|
*/
|
||||||
|
static void prvSetupTimerInterrupt( void );
|
||||||
|
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions implement spin-lock between cores by atomic accesses to Exclusive
|
||||||
|
* Control Register (G0MEVm). There are separated access path between CPU cores,
|
||||||
|
* but they should wait if access to same register
|
||||||
|
*/
|
||||||
|
static void prvExclusiveLock( BaseType_t xFromIsr );
|
||||||
|
static void prvExclusiveRelease( BaseType_t xFromIsr );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to start the first task executing
|
||||||
|
*/
|
||||||
|
extern void vPortStartFirstTask( void );
|
||||||
|
|
||||||
|
/* Scheduler request on each cores which are starting first task and switching
|
||||||
|
* context */
|
||||||
|
volatile BaseType_t xPortScheduleStatus[ configNUMBER_OF_CORES ] = { 0 };
|
||||||
|
|
||||||
|
/* Counts the interrupt nesting depth. A context switch is only performed if
|
||||||
|
* the nesting depth is 0. In addition, the interrupt shares same stack
|
||||||
|
* allocated for each tasks. With supporting nesting interrupt, the stack
|
||||||
|
* may be overflowed.
|
||||||
|
* It is necessary to control maximum stack depth.
|
||||||
|
*/
|
||||||
|
volatile UBaseType_t uxInterruptNesting[ configNUMBER_OF_CORES ] = { 0 };
|
||||||
|
volatile const UBaseType_t uxPortMaxInterruptDepth = configMAX_INT_NESTING;
|
||||||
|
|
||||||
|
/* Count number of nested locks by same cores. The lock is completely released
|
||||||
|
* only if this count is decreased to 0, the lock is separated for task
|
||||||
|
* and isr */
|
||||||
|
UBaseType_t uxLockNesting[ configNUMBER_OF_CORES ][ 2 ] = { 0 };
|
||||||
|
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
|
||||||
|
/* Pointer to exclusive access memory */
|
||||||
|
volatile BaseType_t * pxPortExclusiveReg = ( volatile BaseType_t * ) ( portMEV_BASE_ADDR );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Interrupt handler for OSTM timer which handling tick increment and resulting
|
||||||
|
* to switch context. */
|
||||||
|
void vPortTickISR( void );
|
||||||
|
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
|
||||||
|
/* Yield specific cores by send inter-processor interrupt */
|
||||||
|
void vPortYieldCore( uint32_t xCoreID );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inter-processor interrupt handler. The interrupt is triggered by
|
||||||
|
* portYIELD_CORE().
|
||||||
|
*/
|
||||||
|
void vPortIPIHander( void );
|
||||||
|
|
||||||
|
/* These functions below implement recursive spinlock for exclusive access among
|
||||||
|
* cores. The core will wait until lock will be available, whilst the core which
|
||||||
|
* already had lock can acquire lock without waiting. This function could be
|
||||||
|
* call from task and interrupt context, the critical section is called
|
||||||
|
* as in ISR */
|
||||||
|
void vPortRecursiveLockAcquire( BaseType_t xCoreID, BaseType_t xFromIsr );
|
||||||
|
void vPortRecursiveLockRelease( BaseType_t xCoreID, BaseType_t xFromIsr );
|
||||||
|
|
||||||
|
#endif /* (configNUMBER_OF_CORES > 1) */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These below functions implement interrupt mask from interrupt. They are not
|
||||||
|
* called in nesting, it is protected by FreeRTOS kernel.
|
||||||
|
*/
|
||||||
|
portLONG xPortSetInterruptMask( void )
|
||||||
|
{
|
||||||
|
portLONG ulPSWValue = portSTSR( portPSW_REGISTER_ID );
|
||||||
|
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
/* It returns current value of Program Status Word register */
|
||||||
|
return ulPSWValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortClearInterruptMask( portLONG uxSavedInterruptStatus )
|
||||||
|
{
|
||||||
|
portLONG ulPSWValue = portSTSR( portPSW_REGISTER_ID );
|
||||||
|
|
||||||
|
/* Interrupt Disable status is indicates by bit#5 of PSW
|
||||||
|
* (1: Interrupt is disabled; 0: Interrupt is enabled) */
|
||||||
|
|
||||||
|
/* Revert to the status before interrupt mask. */
|
||||||
|
ulPSWValue &= ( ~( portPSW_ID_MASK ) );
|
||||||
|
ulPSWValue |= ( portPSW_ID_MASK & uxSavedInterruptStatus );
|
||||||
|
portLDSR( portPSW_REGISTER_ID, ulPSWValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using CC-RH intrinsic function to get HTCFG0 (regID, selID) = (0,2)
|
||||||
|
* Core ID is indicates by bit HTCFG0.PEID located at bit 18 to 16
|
||||||
|
* Bit 31 to 19 are read only and always be read as 0. HTCFG0.PEID is 1 and 2
|
||||||
|
* corresponding to core 0 (PE1) and core 1 (PE2). It is adjusted to 0 and 1.
|
||||||
|
*/
|
||||||
|
BaseType_t xPortGET_CORE_ID( void )
|
||||||
|
{
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
return ( portSTSR_CCRH( 0, 2 ) >> 16 ) - 1;
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* In single core, xPortGET_CORE_ID is used in this port only.
|
||||||
|
* The dummy core ID could be controlled inside this port. */
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This port supports both multi-cores and single-core, whilst TCB stack
|
||||||
|
* variables are different which are respectively pxCurrentTCB (single-core)
|
||||||
|
* and pxCurrentTCBs[] (multiple-cores). This function is defined to obtains
|
||||||
|
* TCBs of current cores. Also, the C function could switch to corresponding
|
||||||
|
* pointer by pre-compile conditions.
|
||||||
|
*/
|
||||||
|
void * pvPortGetCurrentTCB( void )
|
||||||
|
{
|
||||||
|
void * pvCurrentTCB = ( void * ) xTaskGetCurrentTaskHandle();
|
||||||
|
|
||||||
|
configASSERT( pvCurrentTCB != NULL );
|
||||||
|
|
||||||
|
return pvCurrentTCB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function checks if a context switch is required and, if so, updates
|
||||||
|
* the scheduler status for the core on which the function is called. The
|
||||||
|
* scheduler status is set to indicate that a task switch should occur.
|
||||||
|
*/
|
||||||
|
void vPortSetSwitch( BaseType_t xSwitchRequired )
|
||||||
|
{
|
||||||
|
if( xSwitchRequired != pdFALSE )
|
||||||
|
{
|
||||||
|
xPortScheduleStatus[ xPortGET_CORE_ID() ] = PORT_SCHEDULER_TASKSWITCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the stack of a new task so it is ready to be placed under the
|
||||||
|
* scheduler control. The registers have to be placed on the stack in the
|
||||||
|
* order that the port expects to find them.
|
||||||
|
*
|
||||||
|
* @param[in] pxTopOfStack Pointer to top of this task's stack
|
||||||
|
* @param[in] pxCode Task function, stored as initial PC for the task
|
||||||
|
* @param[in] pvParameters Parameters for task
|
||||||
|
*/
|
||||||
|
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. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* R31 (LP) */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R5; /* R5 (TP) */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R6 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R7; /* R7 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R8; /* R8 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R9; /* R9 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R10; /* R10 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R11; /* R11 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R12; /* R12 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R13; /* R13 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R14; /* R14 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R15; /* R15 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R16; /* R16 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R17; /* R17 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R18; /* R18 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R19; /* R19 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R20; /* R20 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R21; /* R21 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R22; /* R22 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R23; /* R23 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R24; /* R24 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R25; /* R25 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R26; /* R26 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R27; /* R27 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R28; /* R28 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R29; /* R29 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R30; /* R30 (EP) */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R1; /* R1 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R2; /* R2 */
|
||||||
|
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
/* Keep System pre-configuration (HV, CUx, EBV) as current setting in
|
||||||
|
* PSW register */
|
||||||
|
*pxTopOfStack = ( StackType_t ) ( portCURRENT_PSW_VALUE & portINITIAL_PSW_MASK ); /* EIPSW */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) pxCode; /* EIPC */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* EIIC */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) ( portCURRENT_PSW_VALUE & portINITIAL_PSW_MASK ); /* CTPSW */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* CTPC */
|
||||||
|
|
||||||
|
/* __FPU is defined by CCRH compiler if FPU is enabled */
|
||||||
|
#if ( configENABLE_FPU == 1 )
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) ( portCURRENT_FPSR_VALUE & portINITIAL_FPSR_MASK ); /* FPSR */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* FPEPC */
|
||||||
|
#endif /* (configENABLE_FPU == 1) */
|
||||||
|
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configures the tick frequency and starts the first task.
|
||||||
|
*/
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
BaseType_t xCurrentCore = xPortGET_CORE_ID();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Prevent interrupt by timer interrupt during starting first task.
|
||||||
|
* The interrupt shall be enabled automatically by being restored from
|
||||||
|
* task stack */
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
/* Setup the tick interrupt */
|
||||||
|
configSETUP_TICK_INTERRUPT();
|
||||||
|
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
/* Start scheduler on other cores */
|
||||||
|
for( uint16_t xCoreID = 0; xCoreID < configNUMBER_OF_CORES; xCoreID++ )
|
||||||
|
{
|
||||||
|
if( xCoreID != xCurrentCore )
|
||||||
|
{
|
||||||
|
/* Send yielding request to other cores with flag to start
|
||||||
|
* first task. TaskContextSwitch is not executed */
|
||||||
|
xPortScheduleStatus[ xCoreID ] = PORT_SCHEDULER_STARTFIRSTTASK;
|
||||||
|
vPortYieldCore( xCoreID );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Nothing to do. The first task is started in this call by
|
||||||
|
* below vPortStartFirstTask() */
|
||||||
|
xPortScheduleStatus[ xCoreID ] = PORT_SCHEDULER_NOREQUEST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
|
||||||
|
|
||||||
|
/* Start first task in primary core */
|
||||||
|
vPortStartFirstTask();
|
||||||
|
|
||||||
|
/* Should never get here as the tasks will now be executing! */
|
||||||
|
prvTaskExitError();
|
||||||
|
|
||||||
|
/* To prevent compiler warnings in the case that the application writer
|
||||||
|
* overrides this functionality by defining configTASK_RETURN_ADDRESS.
|
||||||
|
* Call vTaskSwitchContext() so link time optimization does not remove
|
||||||
|
* the symbol. */
|
||||||
|
vTaskSwitchContext(
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
xCurrentCore
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
return pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to catch tasks that attempt to return from their implementing function.
|
||||||
|
*/
|
||||||
|
static void prvTaskExitError( void )
|
||||||
|
{
|
||||||
|
/* 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 ).
|
||||||
|
*
|
||||||
|
* Artificially force an assert() to be triggered if configASSERT() is
|
||||||
|
* defined, then stop here so application writers can catch the error. */
|
||||||
|
|
||||||
|
/* This statement will always fail, triggering the assert */
|
||||||
|
configASSERT( pdFALSE );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following statement may be unreachable because configASSERT(pdFALSE)
|
||||||
|
* always triggers an assertion failure, which typically halts program
|
||||||
|
* execution.
|
||||||
|
* The warning may be reported to indicate to indicate that the compiler
|
||||||
|
* detects the subsequent code will not be executed.
|
||||||
|
* The warning is acceptable to ensure program is halt regardless of
|
||||||
|
* configASSERT(pdFALSE) implementation
|
||||||
|
*/
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
for( ; ; )
|
||||||
|
{
|
||||||
|
/* Infinite loop to ensure the function does not return. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEndScheduler( void )
|
||||||
|
{
|
||||||
|
/* Not implemented in ports where there is nothing to return to.
|
||||||
|
* Artificially force an assert. */
|
||||||
|
configASSERT( pdFALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
|
||||||
|
void vPortYieldCore( uint32_t xCoreID )
|
||||||
|
{
|
||||||
|
/* Check if we need to yield on a different core */
|
||||||
|
if( xCoreID != xPortGET_CORE_ID() )
|
||||||
|
{
|
||||||
|
volatile uint32_t * pulIPIRReg;
|
||||||
|
|
||||||
|
/* Determine the IPI register based on the target core ID */
|
||||||
|
pulIPIRReg = ( volatile uint32_t * ) ( portIPIR_BASE_ADDR );
|
||||||
|
|
||||||
|
/*Inter-processor interrupt generates an interrupt request by
|
||||||
|
* writing 1 to applicable bits of target cores. The interrupt
|
||||||
|
* should be enabled by application in corresponding cores
|
||||||
|
* including PSW.ID (EI instruction) and interrupt control setting
|
||||||
|
* for ICIPIRn channel (interrupt mask, vector method)
|
||||||
|
*/
|
||||||
|
*pulIPIRReg = ( 1 << xCoreID );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Yielding current core */
|
||||||
|
vPortYield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for inter-processor interrupt in second cores. The interrupt is
|
||||||
|
* triggered by portYIELD_CORE(). vTaskSwitchContext() is invoked to
|
||||||
|
* switch tasks
|
||||||
|
*/
|
||||||
|
void vPortIPIHander( void )
|
||||||
|
{
|
||||||
|
BaseType_t xCurrentCore = xPortGET_CORE_ID();
|
||||||
|
|
||||||
|
/* 1st execution starts 1st task, TaskSwitchContext is not executed */
|
||||||
|
if( PORT_SCHEDULER_STARTFIRSTTASK != xPortScheduleStatus[ xCurrentCore ] )
|
||||||
|
{
|
||||||
|
xPortScheduleStatus[ xCurrentCore ] = PORT_SCHEDULER_TASKSWITCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#endif /* (configNUMBER_OF_CORES > 1) */
|
||||||
|
|
||||||
|
void vPortTickISR( void )
|
||||||
|
{
|
||||||
|
/* In case of multicores with SMP, xTaskIncrementTick is required to
|
||||||
|
* called in critical section to avoid conflict resource as this function
|
||||||
|
* could be called by xTaskResumeAll() from any cores. */
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
BaseType_t xSavedInterruptStatus;
|
||||||
|
|
||||||
|
xSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Increment the RTOS tick. */
|
||||||
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
|
{
|
||||||
|
/* Pend a context switch. */
|
||||||
|
xPortScheduleStatus[ xPortGET_CORE_ID() ] = PORT_SCHEDULER_TASKSWITCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
portEXIT_CRITICAL_FROM_ISR( xSavedInterruptStatus );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSetupTimerInterrupt( void )
|
||||||
|
{
|
||||||
|
volatile uint32_t * pulOSTMIntReg;
|
||||||
|
|
||||||
|
/* Interrupt configuration for OSTM Timer
|
||||||
|
* By default, the second lowest priority is set for timer interrupt to
|
||||||
|
* avoid blocking other interrupt. Normally, user could set the lowest
|
||||||
|
* priority for non-critical event. It try to keep timer on time.
|
||||||
|
* In addition, direct vector table is used by default.
|
||||||
|
*/
|
||||||
|
pulOSTMIntReg = ( volatile uint32_t * ) portOSTM_EIC_ADDR;
|
||||||
|
*pulOSTMIntReg = ( portINT_PROCESSING_ENABLED | portINT_DIRECT_VECTOR | portINT_PRIORITY_LEVEL14 );
|
||||||
|
|
||||||
|
/* Set OSTM0 control setting */
|
||||||
|
*( ( volatile uint32_t * ) portOSTM0CTL_ADDR ) =
|
||||||
|
( portOSTM_MODE_INTERVAL_TIMER | portOSTM_START_INTERRUPT_DISABLE );
|
||||||
|
*( ( volatile uint32_t * ) portOSTM0CMP_ADDR ) =
|
||||||
|
( ( configCPU_CLOCK_HZ / configTIMER_PRESCALE ) / configTICK_RATE_HZ ) - 1;
|
||||||
|
|
||||||
|
/* Enable OSTM0 operation */
|
||||||
|
*( ( volatile uint32_t * ) portOSTM0TS_ADDR ) = portOSTM_COUNTER_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These functions implement spin-lock mechanism among cores using hardware
|
||||||
|
* exclusive control with atomic access by CLR1 and SET1 instruction.
|
||||||
|
* Nesting calls to these APIs are possible.
|
||||||
|
*/
|
||||||
|
#pragma inline_asm prvExclusiveLock
|
||||||
|
static void prvExclusiveLock( BaseType_t xBitPosition )
|
||||||
|
{
|
||||||
|
/* No problem with r19, CCRH does not required to restore same value
|
||||||
|
* before and after function call. */
|
||||||
|
mov # _pxPortExclusiveReg, r19
|
||||||
|
ld.w 0[ r19 ], r19
|
||||||
|
|
||||||
|
prvExclusiveLock_Lock:
|
||||||
|
|
||||||
|
/* r6 is xBitPosition */
|
||||||
|
set1 r6, [ r19 ]
|
||||||
|
bz prvExclusiveLock_Lock_success
|
||||||
|
snooze
|
||||||
|
br prvExclusiveLock_Lock
|
||||||
|
|
||||||
|
prvExclusiveLock_Lock_success:
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#pragma inline_asm prvExclusiveRelease
|
||||||
|
static void prvExclusiveRelease( BaseType_t xBitPosition )
|
||||||
|
{
|
||||||
|
mov # _pxPortExclusiveReg, r19
|
||||||
|
ld.w 0[ r19 ], r19
|
||||||
|
|
||||||
|
/* r6 is xBitPosition */
|
||||||
|
clr1 r6, [ r19 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
void vPortRecursiveLockAcquire( BaseType_t xCoreID, BaseType_t xFromIsr )
|
||||||
|
{
|
||||||
|
BaseType_t xSavedInterruptStatus;
|
||||||
|
BaseType_t xBitPosition = ( xFromIsr == pdTRUE );
|
||||||
|
|
||||||
|
xSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
|
||||||
|
if( uxLockNesting[ xCoreID ][ xBitPosition ] == 0 )
|
||||||
|
{
|
||||||
|
prvExclusiveLock( xBitPosition );
|
||||||
|
}
|
||||||
|
|
||||||
|
uxLockNesting[ xCoreID ][ xBitPosition ]++;
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( xSavedInterruptStatus );
|
||||||
|
}
|
||||||
|
|
||||||
|
void vPortRecursiveLockRelease( BaseType_t xCoreID, BaseType_t xFromIsr )
|
||||||
|
{
|
||||||
|
BaseType_t xSavedInterruptStatus;
|
||||||
|
BaseType_t xBitPosition = ( xFromIsr == pdTRUE );
|
||||||
|
|
||||||
|
xSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
|
||||||
|
/* Sync memory */
|
||||||
|
portSYNCM();
|
||||||
|
|
||||||
|
/* Error check whether vPortRecursiveLockRelease() is not called in
|
||||||
|
* pair with vPortRecursiveLockAcquire() */
|
||||||
|
configASSERT( ( uxLockNesting[ xCoreID ][ xBitPosition ] > 0 ) );
|
||||||
|
uxLockNesting[ xCoreID ][ xBitPosition ]--;
|
||||||
|
|
||||||
|
if( uxLockNesting[ xCoreID ][ xBitPosition ] == 0 )
|
||||||
|
{
|
||||||
|
prvExclusiveRelease( xBitPosition );
|
||||||
|
}
|
||||||
|
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( xSavedInterruptStatus );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#endif /* (configNUMBER_OF_CORES > 1) */
|
||||||
@@ -0,0 +1,331 @@
|
|||||||
|
;/*
|
||||||
|
; * FreeRTOS Kernel V11.3.0
|
||||||
|
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
; *
|
||||||
|
; * SPDX-License-Identifier: MIT
|
||||||
|
; *
|
||||||
|
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
; * this software and associated documentation files (the "Software"), to deal in
|
||||||
|
; * the Software without restriction, including without limitation the rights to
|
||||||
|
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
; * subject to the following conditions:
|
||||||
|
; *
|
||||||
|
; * The above copyright notice and this permission notice shall be included in all
|
||||||
|
; * copies or substantial portions of the Software.
|
||||||
|
; *
|
||||||
|
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
; *
|
||||||
|
; * https://www.FreeRTOS.org
|
||||||
|
; * https://github.com/FreeRTOS
|
||||||
|
; *
|
||||||
|
; */
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; Extern symbols
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
.extern _uxInterruptNesting
|
||||||
|
.extern _uxPortMaxInterruptDepth
|
||||||
|
.extern _xPortScheduleStatus
|
||||||
|
.extern _vTaskSwitchContext
|
||||||
|
.extern _pvPortGetCurrentTCB
|
||||||
|
.extern _vCommonISRHandler
|
||||||
|
.extern _xPortGET_CORE_ID
|
||||||
|
|
||||||
|
.public _vIrq_Handler
|
||||||
|
.public _vPortStartFirstTask
|
||||||
|
.public _vPortYield
|
||||||
|
.public _vTRAP0_Handler
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; Macro definitions
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
EIPC .set 0
|
||||||
|
EIPSW .set 1
|
||||||
|
PSW .set 5
|
||||||
|
FPSR .set 6
|
||||||
|
FPEPC .set 7
|
||||||
|
EIIC .set 13
|
||||||
|
CTPC .set 16
|
||||||
|
CTPSW .set 17
|
||||||
|
EIIC_MSK .set 0x00000FFF
|
||||||
|
FPU_MSK .set 0x00010000
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; portSAVE_CONTEXT
|
||||||
|
; Context saving
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
portSAVE_CONTEXT .macro
|
||||||
|
prepare lp, 0
|
||||||
|
|
||||||
|
; Save general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC into stack.
|
||||||
|
pushsp r5, r30
|
||||||
|
$nowarning
|
||||||
|
pushsp r1, r2
|
||||||
|
$warning
|
||||||
|
|
||||||
|
stsr EIPSW, r15
|
||||||
|
stsr EIPC, r16
|
||||||
|
stsr EIIC, r17
|
||||||
|
stsr CTPSW, r18
|
||||||
|
stsr CTPC, r19
|
||||||
|
pushsp r15, r19
|
||||||
|
|
||||||
|
; Save FPU registers to stack if FPU is enabled
|
||||||
|
mov FPU_MSK, r19
|
||||||
|
tst r15, r19
|
||||||
|
|
||||||
|
; Jump over next 3 instructions: stsr (4 bytes)*2 + pushsp (4 bytes)
|
||||||
|
bz 12
|
||||||
|
stsr FPSR, r18
|
||||||
|
stsr FPEPC, r19
|
||||||
|
pushsp r18, r19
|
||||||
|
|
||||||
|
; Save EIPSW register to stack
|
||||||
|
; Due to the syntax of the pushsp instruction, using r14 as dummy value
|
||||||
|
pushsp r14, r15
|
||||||
|
|
||||||
|
; Get current TCB, the return value is stored in r10 (CCRH compiler)
|
||||||
|
jarl _pvPortGetCurrentTCB, lp
|
||||||
|
st.w sp, 0[r10]
|
||||||
|
|
||||||
|
.endm
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; portRESTORE_CONTEXT
|
||||||
|
; Context restoring
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
portRESTORE_CONTEXT .macro
|
||||||
|
; Current TCB is returned by r10 (CCRH compiler)
|
||||||
|
jarl _pvPortGetCurrentTCB, lp
|
||||||
|
ld.w 0[r10], sp ; Restore the stack pointer from the TCB
|
||||||
|
|
||||||
|
; Restore FPU registers if FPU is enabled
|
||||||
|
mov FPU_MSK, r19
|
||||||
|
; Restore EIPSW register to check FPU
|
||||||
|
; Due to the syntax of the popsp instruction, using r14 as dummy value
|
||||||
|
popsp r14, r15
|
||||||
|
tst r15, r19
|
||||||
|
; Jump over next 3 instructions: stsr (4 bytes)*2 + popsp (4 bytes)
|
||||||
|
bz 12
|
||||||
|
popsp r18, r19
|
||||||
|
ldsr r19, FPEPC
|
||||||
|
ldsr r18, FPSR
|
||||||
|
|
||||||
|
;Restore general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC
|
||||||
|
popsp r15, r19
|
||||||
|
ldsr r19, CTPC
|
||||||
|
ldsr r18, CTPSW
|
||||||
|
ldsr r17, EIIC
|
||||||
|
ldsr r16, EIPC
|
||||||
|
ldsr r15, EIPSW
|
||||||
|
|
||||||
|
$nowarning
|
||||||
|
popsp r1, r2
|
||||||
|
$warning
|
||||||
|
popsp r5, r30
|
||||||
|
|
||||||
|
dispose 0, lp
|
||||||
|
.endm
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; Save used registers
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
SAVE_REGISTER .macro
|
||||||
|
; Save general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC into stack.
|
||||||
|
; Callee-Save registers (r20 to r30) are not used in interrupt handler and
|
||||||
|
; guaranteed no change after function call. So, don't need to save register
|
||||||
|
; to optimize the used stack memory.
|
||||||
|
pushsp r5, r19
|
||||||
|
$nowarning
|
||||||
|
pushsp r1, r2
|
||||||
|
$warning
|
||||||
|
|
||||||
|
stsr EIPSW, r19
|
||||||
|
stsr EIPC, r18
|
||||||
|
stsr EIIC, r17
|
||||||
|
mov lp, r16
|
||||||
|
mov ep, r15
|
||||||
|
stsr CTPSW, r14
|
||||||
|
stsr CTPC, r13
|
||||||
|
pushsp r13, r18
|
||||||
|
|
||||||
|
mov FPU_MSK, r16
|
||||||
|
tst r16, r19
|
||||||
|
bz 8
|
||||||
|
stsr FPSR, r17
|
||||||
|
stsr FPEPC, r18
|
||||||
|
|
||||||
|
pushsp r17, r19
|
||||||
|
|
||||||
|
.endm
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; Restore used registers
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
RESTORE_REGISTER .macro
|
||||||
|
|
||||||
|
mov FPU_MSK, r15
|
||||||
|
popsp r17, r19
|
||||||
|
tst r19, r15
|
||||||
|
bz 8
|
||||||
|
ldsr r18, FPEPC
|
||||||
|
ldsr r17, FPSR
|
||||||
|
|
||||||
|
popsp r13, r18
|
||||||
|
ldsr r13, CTPC
|
||||||
|
ldsr r14, CTPSW
|
||||||
|
mov r15, ep
|
||||||
|
mov r16, lp
|
||||||
|
ldsr r17, EIIC
|
||||||
|
ldsr r18, EIPC
|
||||||
|
ldsr r19, EIPSW
|
||||||
|
|
||||||
|
$nowarning
|
||||||
|
popsp r1, r2
|
||||||
|
$warning
|
||||||
|
popsp r5, r19
|
||||||
|
.endm
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; Start the first task.
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
_vPortStartFirstTask:
|
||||||
|
portRESTORE_CONTEXT
|
||||||
|
eiret
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; _vPortYield
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
_vPortYield:
|
||||||
|
trap 0
|
||||||
|
jmp [lp] ; Return to caller function
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; PortYield handler. This is installed as the TRAP exception handler.
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
_vTRAP0_Handler:
|
||||||
|
;Save the context of the current task.
|
||||||
|
portSAVE_CONTEXT
|
||||||
|
|
||||||
|
; The use case that portYield() is called from interrupt context as nested interrupt.
|
||||||
|
; Context switch should be executed at the most outer of interrupt tree.
|
||||||
|
; In that case, set xPortScheduleStatus to flag context switch in interrupt handler.
|
||||||
|
jarl _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
|
||||||
|
mov r10, r11
|
||||||
|
shl 2, r11
|
||||||
|
mov #_uxInterruptNesting, r19
|
||||||
|
add r11, r19
|
||||||
|
ld.w 0[r19], r18
|
||||||
|
cmp r0, r18
|
||||||
|
be _vTRAP0_Handler_ContextSwitch
|
||||||
|
|
||||||
|
mov #_xPortScheduleStatus, r19
|
||||||
|
add r11, r19
|
||||||
|
|
||||||
|
; Set xPortScheduleStatus[coreID]=PORT_SCHEDULER_TASKSWITCH
|
||||||
|
mov 1, r17
|
||||||
|
st.w r17, 0[r19]
|
||||||
|
br _vTRAP0_Handler_Exit
|
||||||
|
|
||||||
|
_vTRAP0_Handler_ContextSwitch:
|
||||||
|
; Pass coreID (r10) as parameter by r6 (CCRH compiler) in SMP support.
|
||||||
|
mov r10, r6
|
||||||
|
; Call the scheduler to select the next task.
|
||||||
|
; vPortYeild may be called to current core again at the end of vTaskSwitchContext.
|
||||||
|
; This may case nested interrupt, however, it is not necessary to set
|
||||||
|
; uxInterruptNesting (currently 0) for nested trap0 exception. The user interrupt
|
||||||
|
; (EI level interrupt) is not accepted inside of trap0 exception.
|
||||||
|
jarl _vTaskSwitchContext, lp
|
||||||
|
|
||||||
|
_vTRAP0_Handler_Exit:
|
||||||
|
; Restore the context of the next task to run.
|
||||||
|
portRESTORE_CONTEXT
|
||||||
|
eiret
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; _Irq_Handler
|
||||||
|
; Handler interrupt service routine (ISR).
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
_vIrq_Handler:
|
||||||
|
; Save used registers.
|
||||||
|
SAVE_REGISTER
|
||||||
|
|
||||||
|
; Get core ID by HTCFG0, thread configuration register.
|
||||||
|
; Then, increase nesting count for current core.
|
||||||
|
jarl _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
|
||||||
|
shl 2, r10
|
||||||
|
mov r10, r17
|
||||||
|
|
||||||
|
mov #_uxInterruptNesting, r19
|
||||||
|
add r17, r19
|
||||||
|
ld.w 0[r19], r18
|
||||||
|
addi 0x1, r18, r16
|
||||||
|
st.w r16, 0[r19]
|
||||||
|
|
||||||
|
pushsp r17, r19
|
||||||
|
|
||||||
|
;Call the interrupt handler.
|
||||||
|
stsr EIIC, r6
|
||||||
|
andi EIIC_MSK, r6, r6
|
||||||
|
|
||||||
|
; Do not enable interrupt for nesting. Stackover flow may occurs if the
|
||||||
|
; depth of nesting interrupt is exceeded.
|
||||||
|
mov #_uxPortMaxInterruptDepth, r19
|
||||||
|
ld.w 0[r19], r15
|
||||||
|
cmp r15, r16
|
||||||
|
bge 4 ; Jump over ei instruction
|
||||||
|
ei
|
||||||
|
jarl _vCommonISRHandler, lp
|
||||||
|
di
|
||||||
|
synce
|
||||||
|
|
||||||
|
popsp r17, r19
|
||||||
|
st.w r18, 0[r19] ; Restore the old nesting count.
|
||||||
|
|
||||||
|
; A context switch if no nesting interrupt.
|
||||||
|
cmp 0x0, r18
|
||||||
|
bne _vIrq_Handler_NotSwitchContext
|
||||||
|
|
||||||
|
; Check if context switch is requested.
|
||||||
|
mov #_xPortScheduleStatus, r19
|
||||||
|
add r17, r19
|
||||||
|
ld.w 0[r19], r18
|
||||||
|
cmp r0, r18
|
||||||
|
bne _vIrq_Handler_SwitchContext
|
||||||
|
|
||||||
|
_vIrq_Handler_NotSwitchContext:
|
||||||
|
; No context switch. Restore used registers
|
||||||
|
RESTORE_REGISTER
|
||||||
|
eiret
|
||||||
|
|
||||||
|
;This sequence is executed for primary core only to switch context
|
||||||
|
_vIrq_Handler_SwitchContext:
|
||||||
|
; Clear the context switch pending flag.
|
||||||
|
st.w r0, 0[r19]
|
||||||
|
|
||||||
|
add -1, r18
|
||||||
|
bnz _vIrq_Handler_StartFirstTask
|
||||||
|
; Restore used registers before saving the context to the task stack.
|
||||||
|
RESTORE_REGISTER
|
||||||
|
portSAVE_CONTEXT
|
||||||
|
|
||||||
|
; Get Core ID and pass to vTaskSwitchContext as parameter (CCRH compiler)
|
||||||
|
; The parameter is unused in single core, no problem with this redudant setting
|
||||||
|
jarl _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
|
||||||
|
mov r10, r6
|
||||||
|
|
||||||
|
; vPortYeild may be called to current core again at the end of vTaskSwitchContext.
|
||||||
|
; This may case nested interrupt, however, it is not necessary to set
|
||||||
|
; uxInterruptNesting (currently 0) for trap0 exception. The user interrupt
|
||||||
|
; (EI level interrupt) is not accepted inside of trap0 exception.
|
||||||
|
jarl _vTaskSwitchContext, lp ;
|
||||||
|
portRESTORE_CONTEXT
|
||||||
|
eiret
|
||||||
|
|
||||||
|
_vIrq_Handler_StartFirstTask:
|
||||||
|
RESTORE_REGISTER
|
||||||
|
jr _vPortStartFirstTask
|
||||||
|
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions - These are a bit legacy and not really used now, other
|
||||||
|
* than portSTACK_TYPE and portBASE_TYPE. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
/* Defines the maximum time when using a wait command in a task */
|
||||||
|
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
#else
|
||||||
|
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specifics */
|
||||||
|
|
||||||
|
#define portSTSR( reg ) __stsr( ( reg ) )
|
||||||
|
#define portLDSR( reg, val ) __ldsr( ( reg ), ( val ) )
|
||||||
|
#define portSTSR_CCRH( reg, sel ) __stsr_rh( ( reg ), ( sel ) )
|
||||||
|
#define portSYNCM() __syncm()
|
||||||
|
|
||||||
|
/* Determine the descending of the stack from high address to address */
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
|
||||||
|
/* Determine the time (in milliseconds) corresponding to each tick */
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
|
||||||
|
/* It is a multiple of 4 (the two lower-order bits of the address = 0),
|
||||||
|
* otherwise it will cause MAE (Misaligned Exception) according to the manual */
|
||||||
|
#define portBYTE_ALIGNMENT ( 4 )
|
||||||
|
|
||||||
|
/* Interrupt control macros. */
|
||||||
|
|
||||||
|
#define portENABLE_INTERRUPTS() __EI() /* Macro to enable all maskable interrupts. */
|
||||||
|
#define portDISABLE_INTERRUPTS() __DI() /* Macro to disable all maskable interrupts. */
|
||||||
|
#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
|
||||||
|
#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS()
|
||||||
|
|
||||||
|
/* SMP build which means configNUM_CORES is relevant */
|
||||||
|
#define portSUPPORT_SMP 1
|
||||||
|
|
||||||
|
#define portMAX_CORE_COUNT 2
|
||||||
|
#ifndef configNUMBER_OF_CORES
|
||||||
|
#define configNUMBER_OF_CORES 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
/* Scheduler utilities */
|
||||||
|
|
||||||
|
/* Called at the end of an ISR that can cause a context switch */
|
||||||
|
extern void vPortSetSwitch( BaseType_t xSwitchRequired );
|
||||||
|
|
||||||
|
#define portEND_SWITCHING_ISR( x ) vPortSetSwitch( x )
|
||||||
|
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
|
||||||
|
/* Use to transfer control from one task to perform other tasks of
|
||||||
|
* higher priority */
|
||||||
|
extern void vPortYield( void );
|
||||||
|
|
||||||
|
#define portYIELD() vPortYield()
|
||||||
|
#if ( configNUMBER_OF_CORES > 1 )
|
||||||
|
|
||||||
|
/* Return the core ID on which the code is running. */
|
||||||
|
extern BaseType_t xPortGET_CORE_ID();
|
||||||
|
|
||||||
|
#define portGET_CORE_ID() xPortGET_CORE_ID()
|
||||||
|
#define coreid xPortGET_CORE_ID()
|
||||||
|
|
||||||
|
/* Request the core ID x to yield. */
|
||||||
|
extern void vPortYieldCore( uint32_t coreID );
|
||||||
|
|
||||||
|
#define portYIELD_CORE( x ) vPortYieldCore( x )
|
||||||
|
|
||||||
|
#define portENTER_CRITICAL_FROM_ISR() vTaskEnterCriticalFromISR()
|
||||||
|
#define portEXIT_CRITICAL_FROM_ISR( x ) vTaskExitCriticalFromISR( x )
|
||||||
|
|
||||||
|
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
|
||||||
|
|
||||||
|
#if ( configNUMBER_OF_CORES == 1 )
|
||||||
|
#define portGET_ISR_LOCK( xCoreID )
|
||||||
|
#define portRELEASE_ISR_LOCK( xCoreID )
|
||||||
|
#define portGET_TASK_LOCK( xCoreID )
|
||||||
|
#define portRELEASE_TASK_LOCK( xCoreID )
|
||||||
|
#else
|
||||||
|
extern void vPortRecursiveLockAcquire( BaseType_t xCoreID, BaseType_t xFromIsr );
|
||||||
|
extern void vPortRecursiveLockRelease( BaseType_t xCoreID, BaseType_t xFromIsr );
|
||||||
|
|
||||||
|
#define portGET_ISR_LOCK( xCoreID ) vPortRecursiveLockAcquire( ( xCoreID ), pdTRUE )
|
||||||
|
#define portRELEASE_ISR_LOCK( xCoreID ) vPortRecursiveLockRelease( ( xCoreID ), pdTRUE )
|
||||||
|
#define portGET_TASK_LOCK( xCoreID ) vPortRecursiveLockAcquire( ( xCoreID ), pdFALSE )
|
||||||
|
#define portRELEASE_TASK_LOCK( xCoreID ) vPortRecursiveLockRelease( ( xCoreID ), pdFALSE )
|
||||||
|
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
/* Critical section management. */
|
||||||
|
|
||||||
|
/* The critical nesting functions defined within tasks.c */
|
||||||
|
|
||||||
|
extern void vTaskEnterCritical( void );
|
||||||
|
extern void vTaskExitCritical( void );
|
||||||
|
|
||||||
|
/* Macro to mark the start of a critical code region */
|
||||||
|
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||||
|
|
||||||
|
/* Macro to mark the end of a critical code region */
|
||||||
|
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
/* Macros to set and clear the interrupt mask. */
|
||||||
|
portLONG xPortSetInterruptMask();
|
||||||
|
void vPortClearInterruptMask( portLONG );
|
||||||
|
|
||||||
|
#define portSET_INTERRUPT_MASK() xPortSetInterruptMask()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK( x ) vPortClearInterruptMask( ( x ) )
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( ( x ) )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||||
|
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
@@ -0,0 +1,692 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Implementation of functions defined in portable.h for the ARM CM3 port.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#if ( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
|
||||||
|
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Constants required to manipulate the core. Registers first... */
|
||||||
|
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
|
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
|
#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
|
/* ...then bits in the registers. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
|
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||||
|
#define portNVIC_PEND_SYSTICK_SET_BIT ( 1UL << 26UL )
|
||||||
|
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||||
|
|
||||||
|
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||||
|
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
|
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt priority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||||
|
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||||
|
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||||
|
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
#define portPRIGROUP_SHIFT ( 8UL )
|
||||||
|
|
||||||
|
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||||
|
#define portVECTACTIVE_MASK ( 0xFFUL )
|
||||||
|
|
||||||
|
/* Constants required to set up the initial stack. */
|
||||||
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
|
||||||
|
/* The systick is a 24-bit counter. */
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/* 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 ( 94UL )
|
||||||
|
|
||||||
|
/* For strict compliance with the Cortex-M spec the task start address should
|
||||||
|
* have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||||
|
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||||
|
|
||||||
|
/* Let the user override the default SysTick clock rate. If defined by the
|
||||||
|
* user, this symbol must equal the SysTick clock rate when the CLK bit is 0 in the
|
||||||
|
* configuration register. */
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ )
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT_CONFIG ( portNVIC_SYSTICK_CLK_BIT )
|
||||||
|
#else
|
||||||
|
/* Select the option to clock SysTick not at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT_CONFIG ( 0 )
|
||||||
|
#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 vPortStartFirstTask( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to catch tasks that attempt to return from their implementing function.
|
||||||
|
*/
|
||||||
|
static void prvTaskExitError( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Required to allow portasm.asm access the configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
* setting. */
|
||||||
|
const uint32_t ulMaxSyscallInterruptPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY;
|
||||||
|
|
||||||
|
/* Each task maintains its own interrupt status in the critical nesting
|
||||||
|
* variable. */
|
||||||
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 uint32_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 uint32_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;
|
||||||
|
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||||
|
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
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_XPSR; /* xPSR */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
|
||||||
|
|
||||||
|
/* Save code space by skipping register initialisation. */
|
||||||
|
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||||
|
|
||||||
|
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||||
|
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTaskExitError( void )
|
||||||
|
{
|
||||||
|
/* 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 ).
|
||||||
|
*
|
||||||
|
* 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();
|
||||||
|
|
||||||
|
for( ; ; )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile uint8_t ucOriginalPriority;
|
||||||
|
volatile uint32_t ulImplementedPrioBits = 0;
|
||||||
|
volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
volatile uint8_t ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
* functions can be called. ISR safe functions are those that end in
|
||||||
|
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
* ensure interrupt entry is as fast and simple as possible.
|
||||||
|
*
|
||||||
|
* Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ucOriginalPriority = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Determine the number of priority bits available. First write to all
|
||||||
|
* possible bits. */
|
||||||
|
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||||
|
|
||||||
|
/* Read the value back to see how many bits stuck. */
|
||||||
|
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Use the same mask on the maximum system call priority. */
|
||||||
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Check that the maximum system call priority is nonzero after
|
||||||
|
* accounting for the number of priority bits supported by the
|
||||||
|
* hardware. A priority of 0 is invalid because setting the BASEPRI
|
||||||
|
* register to 0 unmasks all interrupts, and interrupts with priority 0
|
||||||
|
* cannot be masked using BASEPRI.
|
||||||
|
* See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||||
|
configASSERT( ucMaxSysCallPriority );
|
||||||
|
|
||||||
|
/* Check that the bits not implemented in hardware are zero in
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( ~ucMaxPriorityValue ) ) == 0U );
|
||||||
|
|
||||||
|
/* Calculate the maximum acceptable priority group value for the number
|
||||||
|
* of bits read back. */
|
||||||
|
|
||||||
|
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||||
|
{
|
||||||
|
ulImplementedPrioBits++;
|
||||||
|
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ulImplementedPrioBits == 8 )
|
||||||
|
{
|
||||||
|
/* When the hardware implements 8 priority bits, there is no way for
|
||||||
|
* the software to configure PRIGROUP to not have sub-priorities. As
|
||||||
|
* a result, the least significant bit is always used for sub-priority
|
||||||
|
* and there are 128 preemption priorities and 2 sub-priorities.
|
||||||
|
*
|
||||||
|
* This may cause some confusion in some cases - for example, if
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
|
||||||
|
* priority interrupts will be masked in Critical Sections as those
|
||||||
|
* are at the same preemption priority. This may appear confusing as
|
||||||
|
* 4 is higher (numerically lower) priority than
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
|
||||||
|
* have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
* to 4, this confusion does not happen and the behaviour remains the same.
|
||||||
|
*
|
||||||
|
* The following assert ensures that the sub-priority bit in the
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
|
||||||
|
* confusion. */
|
||||||
|
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
|
||||||
|
ulMaxPRIGROUPValue = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift the priority group value back to its position within the AIRCR
|
||||||
|
* register. */
|
||||||
|
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||||
|
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
* value. */
|
||||||
|
*pucFirstUserPriorityRegister = ucOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
|
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
|
||||||
|
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
|
* here already. */
|
||||||
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
|
uxCriticalNesting = 0;
|
||||||
|
|
||||||
|
/* Start the first task. */
|
||||||
|
vPortStartFirstTask();
|
||||||
|
|
||||||
|
/* Should not get here! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
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( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortExitCritical( void )
|
||||||
|
{
|
||||||
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
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. */
|
||||||
|
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
traceISR_ENTER();
|
||||||
|
{
|
||||||
|
/* Increment the RTOS tick. */
|
||||||
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
|
{
|
||||||
|
traceISR_EXIT_TO_SCHEDULER();
|
||||||
|
|
||||||
|
/* A context switch is required. Context switching is performed in
|
||||||
|
* the PendSV interrupt. Pend the PendSV interrupt. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
traceISR_EXIT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
|
||||||
|
#pragma WEAK( vPortSuppressTicksAndSleep )
|
||||||
|
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
* method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm( " cpsid i" );
|
||||||
|
__asm( " dsb" );
|
||||||
|
__asm( " isb" );
|
||||||
|
|
||||||
|
/* 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 )
|
||||||
|
{
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction
|
||||||
|
* above. */
|
||||||
|
__asm( " cpsie i" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 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. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Use the SysTick current-value register to determine the number of
|
||||||
|
* SysTick decrements remaining until the next tick interrupt. If the
|
||||||
|
* current-value register is zero, then there are actually
|
||||||
|
* ulTimerCountsForOneTick decrements remaining, not zero, because the
|
||||||
|
* SysTick requests the interrupt when decrementing from 1 to 0. */
|
||||||
|
ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
if( ulSysTickDecrementsLeft == 0 )
|
||||||
|
{
|
||||||
|
ulSysTickDecrementsLeft = ulTimerCountsForOneTick;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
* tick periods. -1 is used because this code normally executes part
|
||||||
|
* way through the first tick period. But if the SysTick IRQ is now
|
||||||
|
* pending, then clear the IRQ, suppressing the first tick, and correct
|
||||||
|
* the reload value to reflect that the second tick period is already
|
||||||
|
* underway. The expected idle time is always at least two ticks. */
|
||||||
|
ulReloadValue = ulSysTickDecrementsLeft + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
|
||||||
|
if( ( portNVIC_INT_CTRL_REG & portNVIC_PEND_SYSTICK_SET_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PEND_SYSTICK_CLEAR_BIT;
|
||||||
|
ulReloadValue -= ulTimerCountsForOneTick;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
* zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* 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 )
|
||||||
|
{
|
||||||
|
__asm( " dsb" );
|
||||||
|
__asm( " wfi" );
|
||||||
|
__asm( " isb" );
|
||||||
|
}
|
||||||
|
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
* out of sleep mode to execute immediately. See comments above
|
||||||
|
* the cpsid instruction above. */
|
||||||
|
__asm( " cpsie i" );
|
||||||
|
__asm( " dsb" );
|
||||||
|
__asm( " isb" );
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
__asm( " cpsid i" );
|
||||||
|
__asm( " dsb" );
|
||||||
|
__asm( " isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. 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*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine whether the SysTick has already counted to zero. */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt ended the sleep (or is now pending), and
|
||||||
|
* a new tick period has started. Reset portNVIC_SYSTICK_LOAD_REG
|
||||||
|
* with whatever remains of the new tick period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
* underflowed because the post sleep hook did something
|
||||||
|
* that took too long or because the SysTick current-value register
|
||||||
|
* is zero. */
|
||||||
|
if( ( ulCalculatedLoadValue <= ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep. */
|
||||||
|
|
||||||
|
/* Use the SysTick current-value register to determine the
|
||||||
|
* number of SysTick decrements remaining until the expected idle
|
||||||
|
* time would have ended. */
|
||||||
|
ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
#if ( portNVIC_SYSTICK_CLK_BIT_CONFIG != portNVIC_SYSTICK_CLK_BIT )
|
||||||
|
{
|
||||||
|
/* If the SysTick is not using the core clock, the current-
|
||||||
|
* value register might still be zero here. In that case, the
|
||||||
|
* SysTick didn't load from the reload register, and there are
|
||||||
|
* ulReloadValue decrements remaining in the expected idle
|
||||||
|
* time, not zero. */
|
||||||
|
if( ulSysTickDecrementsLeft == 0 )
|
||||||
|
{
|
||||||
|
ulSysTickDecrementsLeft = ulReloadValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */
|
||||||
|
|
||||||
|
/* Work out how long the sleep lasted rounded to complete tick
|
||||||
|
* periods (not the ulReload value which accounted for part
|
||||||
|
* ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - ulSysTickDecrementsLeft;
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again,
|
||||||
|
* then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If
|
||||||
|
* the SysTick is not using the core clock, temporarily configure it to
|
||||||
|
* use the core clock. This configuration forces the SysTick to load
|
||||||
|
* from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next
|
||||||
|
* cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready
|
||||||
|
* to receive the standard value immediately. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
#if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT )
|
||||||
|
{
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
/* The temporary usage of the core clock has served its purpose,
|
||||||
|
* as described above. Resume usage of the other clock. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
|
||||||
|
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
/* The partial tick period already ended. Be sure the SysTick
|
||||||
|
* counts it only once. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
}
|
||||||
|
#endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */
|
||||||
|
|
||||||
|
/* Step the tick to account for any tick periods that elapsed. */
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
|
||||||
|
/* Exit with interrupts enabled. */
|
||||||
|
__asm( " cpsie i" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the systick timer to generate the tick interrupts at the required
|
||||||
|
* frequency.
|
||||||
|
*/
|
||||||
|
#pragma WEAK( vPortSetupTimerInterrupt )
|
||||||
|
void vPortSetupTimerInterrupt( void )
|
||||||
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/* Stop and clear the SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
extern uint32_t ulPortGetIPSR( void );
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
uint8_t ucCurrentPriority;
|
||||||
|
|
||||||
|
ulCurrentInterrupt = ulPortGetIPSR();
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
* an interrupt that has been assigned a priority above
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY 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
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*
|
||||||
|
* 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 configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
|
* 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:
|
||||||
|
* https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
|
||||||
|
* https://www.freertos.org/Why-FreeRTOS/FAQs */
|
||||||
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
|
* that define each interrupt's priority to be split between bits that
|
||||||
|
* define the interrupt's pre-emption priority bits and bits that define
|
||||||
|
* the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
|
* to be pre-emption priority bits. The following assertion will fail if
|
||||||
|
* this is not the case (if some bits represent a sub-priority).
|
||||||
|
*
|
||||||
|
* If the application only uses CMSIS libraries for interrupt
|
||||||
|
* configuration then the correct setting can be achieved on all Cortex-M
|
||||||
|
* devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
* scheduler. Note however that some vendor specific peripheral libraries
|
||||||
|
* assume a non-zero priority group setting, in which cases using a value
|
||||||
|
* of zero will result in unpredictable behaviour. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
;/*
|
||||||
|
; * FreeRTOS Kernel V11.3.0
|
||||||
|
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
; *
|
||||||
|
; * SPDX-License-Identifier: MIT
|
||||||
|
; *
|
||||||
|
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
; * this software and associated documentation files (the "Software"), to deal in
|
||||||
|
; * the Software without restriction, including without limitation the rights to
|
||||||
|
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
; * subject to the following conditions:
|
||||||
|
; *
|
||||||
|
; * The above copyright notice and this permission notice shall be included in all
|
||||||
|
; * copies or substantial portions of the Software.
|
||||||
|
; *
|
||||||
|
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
; *
|
||||||
|
; * https://www.FreeRTOS.org
|
||||||
|
; * https://github.com/FreeRTOS
|
||||||
|
; *
|
||||||
|
; */
|
||||||
|
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
.ref pxCurrentTCB
|
||||||
|
.ref vTaskSwitchContext
|
||||||
|
.ref ulMaxSyscallInterruptPriority
|
||||||
|
|
||||||
|
.def xPortPendSVHandler
|
||||||
|
.def ulPortGetIPSR
|
||||||
|
.def vPortSVCHandler
|
||||||
|
.def vPortStartFirstTask
|
||||||
|
|
||||||
|
NVICOffsetConst: .word 0xE000ED08
|
||||||
|
CPACRConst: .word 0xE000ED88
|
||||||
|
pxCurrentTCBConst: .word pxCurrentTCB
|
||||||
|
ulMaxSyscallInterruptPriorityConst: .word ulMaxSyscallInterruptPriority
|
||||||
|
|
||||||
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
ulPortGetIPSR: .asmfunc
|
||||||
|
mrs r0, ipsr
|
||||||
|
bx r14
|
||||||
|
.endasmfunc
|
||||||
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
vPortSetInterruptMask: .asmfunc
|
||||||
|
push {r0}
|
||||||
|
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||||
|
msr basepri, r0
|
||||||
|
pop {r0}
|
||||||
|
bx r14
|
||||||
|
.endasmfunc
|
||||||
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
xPortPendSVHandler: .asmfunc
|
||||||
|
mrs r0, psp
|
||||||
|
isb
|
||||||
|
|
||||||
|
;/* Get the location of the current TCB. */
|
||||||
|
ldr r3, pxCurrentTCBConst
|
||||||
|
ldr r2, [r3]
|
||||||
|
|
||||||
|
;/* Save the core registers. */
|
||||||
|
stmdb r0!, {r4-r11}
|
||||||
|
|
||||||
|
;/* Save the new top of stack into the first member of the TCB. */
|
||||||
|
str r0, [r2]
|
||||||
|
|
||||||
|
stmdb sp!, {r3, r14}
|
||||||
|
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||||
|
ldr r1, [r0]
|
||||||
|
msr basepri, r1
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
ldmia sp!, {r3, r14}
|
||||||
|
|
||||||
|
;/* The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1]
|
||||||
|
|
||||||
|
;/* Pop the core registers. */
|
||||||
|
ldmia r0!, {r4-r11}
|
||||||
|
|
||||||
|
msr psp, r0
|
||||||
|
isb
|
||||||
|
bx r14
|
||||||
|
.endasmfunc
|
||||||
|
|
||||||
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
vPortSVCHandler: .asmfunc
|
||||||
|
;/* Get the location of the current TCB. */
|
||||||
|
ldr r3, pxCurrentTCBConst
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1]
|
||||||
|
;/* Pop the core registers. */
|
||||||
|
ldmia r0!, {r4-r11}
|
||||||
|
msr psp, r0
|
||||||
|
isb
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
orr r14, #0xd
|
||||||
|
bx r14
|
||||||
|
.endasmfunc
|
||||||
|
|
||||||
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
vPortStartFirstTask: .asmfunc
|
||||||
|
;/* Use the NVIC offset register to locate the stack. */
|
||||||
|
ldr r0, NVICOffsetConst
|
||||||
|
ldr r0, [r0]
|
||||||
|
ldr r0, [r0]
|
||||||
|
;/* Set the msp back to the start of the stack. */
|
||||||
|
msr msp, r0
|
||||||
|
;/* Clear 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 SVC stack for lazy saving of FPU
|
||||||
|
;registers. */
|
||||||
|
mov r0, #0
|
||||||
|
msr control, r0
|
||||||
|
;/* Call SVC to start the first task. */
|
||||||
|
cpsie i
|
||||||
|
cpsie f
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
svc #0
|
||||||
|
.endasmfunc
|
||||||
|
|
||||||
|
; -----------------------------------------------------------
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
#else
|
||||||
|
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specifics. */
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Compiler directives. */
|
||||||
|
#define portWEAK_SYMBOL __attribute__( ( weak ) )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler utilities. */
|
||||||
|
#define portYIELD() \
|
||||||
|
{ \
|
||||||
|
/* Set a PendSV to request a context switch. */ \
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||||
|
__asm( " dsb"); \
|
||||||
|
__asm( " isb"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||||
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if( xSwitchRequired != pdFALSE ) \
|
||||||
|
{ \
|
||||||
|
traceISR_EXIT_TO_SCHEDULER(); \
|
||||||
|
portYIELD(); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
traceISR_EXIT(); \
|
||||||
|
} \
|
||||||
|
} while( 0 )
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* 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 = ( 31 - __clz( ( uxReadyPriorities ) ) )
|
||||||
|
|
||||||
|
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
extern void vPortEnterCritical( void );
|
||||||
|
extern void vPortExitCritical( void );
|
||||||
|
|
||||||
|
#define portDISABLE_INTERRUPTS() \
|
||||||
|
{ \
|
||||||
|
_set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
|
||||||
|
__asm( " dsb"); \
|
||||||
|
__asm( " isb"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 )
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb")
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||||
|
* 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 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* portNOP() is not required by this port. */
|
||||||
|
#define portNOP()
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
@@ -0,0 +1,717 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Implementation of functions defined in portable.h for the ARM CM4F port.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#ifndef __TI_VFP_SUPPORT__
|
||||||
|
#error This port can only be used when the project options are configured to enable hardware floating point support.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
|
||||||
|
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Constants required to manipulate the core. Registers first... */
|
||||||
|
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
|
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
|
#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
|
/* ...then bits in the registers. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
|
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||||
|
#define portNVIC_PEND_SYSTICK_SET_BIT ( 1UL << 26UL )
|
||||||
|
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||||
|
|
||||||
|
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||||
|
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
|
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt priority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||||
|
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||||
|
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||||
|
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
#define portPRIGROUP_SHIFT ( 8UL )
|
||||||
|
|
||||||
|
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||||
|
#define portVECTACTIVE_MASK ( 0xFFUL )
|
||||||
|
|
||||||
|
/* Constants required to manipulate the VFP. */
|
||||||
|
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
|
||||||
|
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||||
|
|
||||||
|
/* Constants required to set up the initial stack. */
|
||||||
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
|
||||||
|
|
||||||
|
/* The systick is a 24-bit counter. */
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/* 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 ( 94UL )
|
||||||
|
|
||||||
|
/* For strict compliance with the Cortex-M spec the task start address should
|
||||||
|
* have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||||
|
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||||
|
|
||||||
|
/* Let the user override the default SysTick clock rate. If defined by the
|
||||||
|
* user, this symbol must equal the SysTick clock rate when the CLK bit is 0 in the
|
||||||
|
* configuration register. */
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ )
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT_CONFIG ( portNVIC_SYSTICK_CLK_BIT )
|
||||||
|
#else
|
||||||
|
/* Select the option to clock SysTick not at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT_CONFIG ( 0 )
|
||||||
|
#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 vPortStartFirstTask( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn the VFP on.
|
||||||
|
*/
|
||||||
|
extern void vPortEnableVFP( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to catch tasks that attempt to return from their implementing function.
|
||||||
|
*/
|
||||||
|
static void prvTaskExitError( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Required to allow portasm.asm access the configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
* setting. */
|
||||||
|
const uint32_t ulMaxSyscallInterruptPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY;
|
||||||
|
|
||||||
|
/* Each task maintains its own interrupt status in the critical nesting
|
||||||
|
* variable. */
|
||||||
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 uint32_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 uint32_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;
|
||||||
|
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||||
|
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
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_XPSR; /* xPSR */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
|
||||||
|
|
||||||
|
/* Save code space by skipping register initialisation. */
|
||||||
|
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||||
|
|
||||||
|
/* A save method is being used that requires each task to maintain its
|
||||||
|
* own exec return value. */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||||
|
|
||||||
|
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||||
|
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTaskExitError( void )
|
||||||
|
{
|
||||||
|
/* 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 ).
|
||||||
|
*
|
||||||
|
* 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();
|
||||||
|
|
||||||
|
for( ; ; )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile uint8_t ucOriginalPriority;
|
||||||
|
volatile uint32_t ulImplementedPrioBits = 0;
|
||||||
|
volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
volatile uint8_t ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
* functions can be called. ISR safe functions are those that end in
|
||||||
|
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
* ensure interrupt entry is as fast and simple as possible.
|
||||||
|
*
|
||||||
|
* Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ucOriginalPriority = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Determine the number of priority bits available. First write to all
|
||||||
|
* possible bits. */
|
||||||
|
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||||
|
|
||||||
|
/* Read the value back to see how many bits stuck. */
|
||||||
|
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Use the same mask on the maximum system call priority. */
|
||||||
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Check that the maximum system call priority is nonzero after
|
||||||
|
* accounting for the number of priority bits supported by the
|
||||||
|
* hardware. A priority of 0 is invalid because setting the BASEPRI
|
||||||
|
* register to 0 unmasks all interrupts, and interrupts with priority 0
|
||||||
|
* cannot be masked using BASEPRI.
|
||||||
|
* See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||||
|
configASSERT( ucMaxSysCallPriority );
|
||||||
|
|
||||||
|
/* Check that the bits not implemented in hardware are zero in
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||||
|
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( ~ucMaxPriorityValue ) ) == 0U );
|
||||||
|
|
||||||
|
/* Calculate the maximum acceptable priority group value for the number
|
||||||
|
* of bits read back. */
|
||||||
|
|
||||||
|
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||||
|
{
|
||||||
|
ulImplementedPrioBits++;
|
||||||
|
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ulImplementedPrioBits == 8 )
|
||||||
|
{
|
||||||
|
/* When the hardware implements 8 priority bits, there is no way for
|
||||||
|
* the software to configure PRIGROUP to not have sub-priorities. As
|
||||||
|
* a result, the least significant bit is always used for sub-priority
|
||||||
|
* and there are 128 preemption priorities and 2 sub-priorities.
|
||||||
|
*
|
||||||
|
* This may cause some confusion in some cases - for example, if
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
|
||||||
|
* priority interrupts will be masked in Critical Sections as those
|
||||||
|
* are at the same preemption priority. This may appear confusing as
|
||||||
|
* 4 is higher (numerically lower) priority than
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
|
||||||
|
* have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
* to 4, this confusion does not happen and the behaviour remains the same.
|
||||||
|
*
|
||||||
|
* The following assert ensures that the sub-priority bit in the
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
|
||||||
|
* confusion. */
|
||||||
|
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
|
||||||
|
ulMaxPRIGROUPValue = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift the priority group value back to its position within the AIRCR
|
||||||
|
* register. */
|
||||||
|
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||||
|
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
* value. */
|
||||||
|
*pucFirstUserPriorityRegister = ucOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
|
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
|
||||||
|
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
|
* here already. */
|
||||||
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
|
uxCriticalNesting = 0;
|
||||||
|
|
||||||
|
/* Ensure the VFP is enabled - it should be anyway. */
|
||||||
|
vPortEnableVFP();
|
||||||
|
|
||||||
|
/* Lazy save always. */
|
||||||
|
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
|
||||||
|
|
||||||
|
/* Start the first task. */
|
||||||
|
vPortStartFirstTask();
|
||||||
|
|
||||||
|
/* Should not get here! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
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( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortExitCritical( void )
|
||||||
|
{
|
||||||
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
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. */
|
||||||
|
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
traceISR_ENTER();
|
||||||
|
{
|
||||||
|
/* Increment the RTOS tick. */
|
||||||
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
|
{
|
||||||
|
traceISR_EXIT_TO_SCHEDULER();
|
||||||
|
|
||||||
|
/* A context switch is required. Context switching is performed in
|
||||||
|
* the PendSV interrupt. Pend the PendSV interrupt. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
traceISR_EXIT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
|
||||||
|
#pragma WEAK( vPortSuppressTicksAndSleep )
|
||||||
|
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
* method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm( " cpsid i" );
|
||||||
|
__asm( " dsb" );
|
||||||
|
__asm( " isb" );
|
||||||
|
|
||||||
|
/* 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 )
|
||||||
|
{
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction
|
||||||
|
* above. */
|
||||||
|
__asm( " cpsie i" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 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. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Use the SysTick current-value register to determine the number of
|
||||||
|
* SysTick decrements remaining until the next tick interrupt. If the
|
||||||
|
* current-value register is zero, then there are actually
|
||||||
|
* ulTimerCountsForOneTick decrements remaining, not zero, because the
|
||||||
|
* SysTick requests the interrupt when decrementing from 1 to 0. */
|
||||||
|
ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
if( ulSysTickDecrementsLeft == 0 )
|
||||||
|
{
|
||||||
|
ulSysTickDecrementsLeft = ulTimerCountsForOneTick;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
* tick periods. -1 is used because this code normally executes part
|
||||||
|
* way through the first tick period. But if the SysTick IRQ is now
|
||||||
|
* pending, then clear the IRQ, suppressing the first tick, and correct
|
||||||
|
* the reload value to reflect that the second tick period is already
|
||||||
|
* underway. The expected idle time is always at least two ticks. */
|
||||||
|
ulReloadValue = ulSysTickDecrementsLeft + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
|
||||||
|
if( ( portNVIC_INT_CTRL_REG & portNVIC_PEND_SYSTICK_SET_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PEND_SYSTICK_CLEAR_BIT;
|
||||||
|
ulReloadValue -= ulTimerCountsForOneTick;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
* zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* 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 )
|
||||||
|
{
|
||||||
|
__asm( " dsb" );
|
||||||
|
__asm( " wfi" );
|
||||||
|
__asm( " isb" );
|
||||||
|
}
|
||||||
|
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
* out of sleep mode to execute immediately. See comments above
|
||||||
|
* the cpsid instruction above. */
|
||||||
|
__asm( " cpsie i" );
|
||||||
|
__asm( " dsb" );
|
||||||
|
__asm( " isb" );
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
__asm( " cpsid i" );
|
||||||
|
__asm( " dsb" );
|
||||||
|
__asm( " isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. 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*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine whether the SysTick has already counted to zero. */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt ended the sleep (or is now pending), and
|
||||||
|
* a new tick period has started. Reset portNVIC_SYSTICK_LOAD_REG
|
||||||
|
* with whatever remains of the new tick period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
* underflowed because the post sleep hook did something
|
||||||
|
* that took too long or because the SysTick current-value register
|
||||||
|
* is zero. */
|
||||||
|
if( ( ulCalculatedLoadValue <= ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep. */
|
||||||
|
|
||||||
|
/* Use the SysTick current-value register to determine the
|
||||||
|
* number of SysTick decrements remaining until the expected idle
|
||||||
|
* time would have ended. */
|
||||||
|
ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
#if ( portNVIC_SYSTICK_CLK_BIT_CONFIG != portNVIC_SYSTICK_CLK_BIT )
|
||||||
|
{
|
||||||
|
/* If the SysTick is not using the core clock, the current-
|
||||||
|
* value register might still be zero here. In that case, the
|
||||||
|
* SysTick didn't load from the reload register, and there are
|
||||||
|
* ulReloadValue decrements remaining in the expected idle
|
||||||
|
* time, not zero. */
|
||||||
|
if( ulSysTickDecrementsLeft == 0 )
|
||||||
|
{
|
||||||
|
ulSysTickDecrementsLeft = ulReloadValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */
|
||||||
|
|
||||||
|
/* Work out how long the sleep lasted rounded to complete tick
|
||||||
|
* periods (not the ulReload value which accounted for part
|
||||||
|
* ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - ulSysTickDecrementsLeft;
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again,
|
||||||
|
* then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If
|
||||||
|
* the SysTick is not using the core clock, temporarily configure it to
|
||||||
|
* use the core clock. This configuration forces the SysTick to load
|
||||||
|
* from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next
|
||||||
|
* cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready
|
||||||
|
* to receive the standard value immediately. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
#if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT )
|
||||||
|
{
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
/* The temporary usage of the core clock has served its purpose,
|
||||||
|
* as described above. Resume usage of the other clock. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
|
||||||
|
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
/* The partial tick period already ended. Be sure the SysTick
|
||||||
|
* counts it only once. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
}
|
||||||
|
#endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */
|
||||||
|
|
||||||
|
/* Step the tick to account for any tick periods that elapsed. */
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
|
||||||
|
/* Exit with interrupts enabled. */
|
||||||
|
__asm( " cpsie i" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the systick timer to generate the tick interrupts at the required
|
||||||
|
* frequency.
|
||||||
|
*/
|
||||||
|
#pragma WEAK( vPortSetupTimerInterrupt )
|
||||||
|
void vPortSetupTimerInterrupt( void )
|
||||||
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/* Stop and clear the SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
extern uint32_t ulPortGetIPSR( void );
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
uint8_t ucCurrentPriority;
|
||||||
|
|
||||||
|
ulCurrentInterrupt = ulPortGetIPSR();
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
* an interrupt that has been assigned a priority above
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY 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
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*
|
||||||
|
* 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 configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
|
* 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:
|
||||||
|
* https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
|
||||||
|
* https://www.freertos.org/Why-FreeRTOS/FAQs */
|
||||||
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
|
* that define each interrupt's priority to be split between bits that
|
||||||
|
* define the interrupt's pre-emption priority bits and bits that define
|
||||||
|
* the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
|
* to be pre-emption priority bits. The following assertion will fail if
|
||||||
|
* this is not the case (if some bits represent a sub-priority).
|
||||||
|
*
|
||||||
|
* If the application only uses CMSIS libraries for interrupt
|
||||||
|
* configuration then the correct setting can be achieved on all Cortex-M
|
||||||
|
* devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
* scheduler. Note however that some vendor specific peripheral libraries
|
||||||
|
* assume a non-zero priority group setting, in which cases using a value
|
||||||
|
* of zero will result in unpredictable behaviour. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
;/*
|
||||||
|
; * FreeRTOS Kernel V11.3.0
|
||||||
|
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
; *
|
||||||
|
; * SPDX-License-Identifier: MIT
|
||||||
|
; *
|
||||||
|
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
; * this software and associated documentation files (the "Software"), to deal in
|
||||||
|
; * the Software without restriction, including without limitation the rights to
|
||||||
|
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
; * subject to the following conditions:
|
||||||
|
; *
|
||||||
|
; * The above copyright notice and this permission notice shall be included in all
|
||||||
|
; * copies or substantial portions of the Software.
|
||||||
|
; *
|
||||||
|
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
; *
|
||||||
|
; * https://www.FreeRTOS.org
|
||||||
|
; * https://github.com/FreeRTOS
|
||||||
|
; *
|
||||||
|
; */
|
||||||
|
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
.ref pxCurrentTCB
|
||||||
|
.ref vTaskSwitchContext
|
||||||
|
.ref ulMaxSyscallInterruptPriority
|
||||||
|
|
||||||
|
.def xPortPendSVHandler
|
||||||
|
.def ulPortGetIPSR
|
||||||
|
.def vPortSVCHandler
|
||||||
|
.def vPortStartFirstTask
|
||||||
|
.def vPortEnableVFP
|
||||||
|
|
||||||
|
NVICOffsetConst: .word 0xE000ED08
|
||||||
|
CPACRConst: .word 0xE000ED88
|
||||||
|
pxCurrentTCBConst: .word pxCurrentTCB
|
||||||
|
ulMaxSyscallInterruptPriorityConst: .word ulMaxSyscallInterruptPriority
|
||||||
|
|
||||||
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
ulPortGetIPSR: .asmfunc
|
||||||
|
mrs r0, ipsr
|
||||||
|
bx r14
|
||||||
|
.endasmfunc
|
||||||
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
vPortSetInterruptMask: .asmfunc
|
||||||
|
push {r0}
|
||||||
|
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||||
|
msr basepri, r0
|
||||||
|
pop {r0}
|
||||||
|
bx r14
|
||||||
|
.endasmfunc
|
||||||
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
xPortPendSVHandler: .asmfunc
|
||||||
|
mrs r0, psp
|
||||||
|
isb
|
||||||
|
|
||||||
|
;/* Get the location of the current TCB. */
|
||||||
|
ldr r3, pxCurrentTCBConst
|
||||||
|
ldr r2, [r3]
|
||||||
|
|
||||||
|
;/* Is the task using the FPU context? If so, push high vfp registers. */
|
||||||
|
tst r14, #0x10
|
||||||
|
it eq
|
||||||
|
vstmdbeq r0!, {s16-s31}
|
||||||
|
|
||||||
|
;/* Save the core registers. */
|
||||||
|
stmdb r0!, {r4-r11, r14}
|
||||||
|
|
||||||
|
;/* Save the new top of stack into the first member of the TCB. */
|
||||||
|
str r0, [r2]
|
||||||
|
|
||||||
|
stmdb sp!, {r0, r3}
|
||||||
|
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||||
|
ldr r1, [r0]
|
||||||
|
msr basepri, r1
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
ldmia sp!, {r0, r3}
|
||||||
|
|
||||||
|
;/* The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1]
|
||||||
|
|
||||||
|
;/* Pop the core registers. */
|
||||||
|
ldmia r0!, {r4-r11, r14}
|
||||||
|
|
||||||
|
;/* Is the task using the FPU context? If so, pop the high vfp registers
|
||||||
|
;too. */
|
||||||
|
tst r14, #0x10
|
||||||
|
it eq
|
||||||
|
vldmiaeq r0!, {s16-s31}
|
||||||
|
|
||||||
|
msr psp, r0
|
||||||
|
isb
|
||||||
|
bx r14
|
||||||
|
.endasmfunc
|
||||||
|
|
||||||
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
vPortSVCHandler: .asmfunc
|
||||||
|
;/* Get the location of the current TCB. */
|
||||||
|
ldr r3, pxCurrentTCBConst
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1]
|
||||||
|
;/* Pop the core registers. */
|
||||||
|
ldmia r0!, {r4-r11, r14}
|
||||||
|
msr psp, r0
|
||||||
|
isb
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
bx r14
|
||||||
|
.endasmfunc
|
||||||
|
|
||||||
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
vPortStartFirstTask: .asmfunc
|
||||||
|
;/* Use the NVIC offset register to locate the stack. */
|
||||||
|
ldr r0, NVICOffsetConst
|
||||||
|
ldr r0, [r0]
|
||||||
|
ldr r0, [r0]
|
||||||
|
;/* Set the msp back to the start of the stack. */
|
||||||
|
msr msp, r0
|
||||||
|
;/* Clear 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 SVC stack for lazy saving of FPU
|
||||||
|
;registers. */
|
||||||
|
mov r0, #0
|
||||||
|
msr control, r0
|
||||||
|
;/* Call SVC to start the first task. */
|
||||||
|
cpsie i
|
||||||
|
cpsie f
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
svc #0
|
||||||
|
.endasmfunc
|
||||||
|
|
||||||
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
vPortEnableVFP: .asmfunc
|
||||||
|
;/* The FPU enable bits are in the CPACR. */
|
||||||
|
ldr.w r0, CPACRConst
|
||||||
|
ldr r1, [r0]
|
||||||
|
|
||||||
|
;/* Enable CP10 and CP11 coprocessors, then save back. */
|
||||||
|
orr r1, r1, #( 0xf << 20 )
|
||||||
|
str r1, [r0]
|
||||||
|
bx r14
|
||||||
|
.endasmfunc
|
||||||
|
|
||||||
|
.end
|
||||||
|
|
||||||
|
; -----------------------------------------------------------
|
||||||
@@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
#else
|
||||||
|
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specifics. */
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler utilities. */
|
||||||
|
#define portYIELD() \
|
||||||
|
{ \
|
||||||
|
/* Set a PendSV to request a context switch. */ \
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||||
|
__asm( " dsb"); \
|
||||||
|
__asm( " isb"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||||
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if( xSwitchRequired != pdFALSE ) \
|
||||||
|
{ \
|
||||||
|
traceISR_EXIT_TO_SCHEDULER(); \
|
||||||
|
portYIELD(); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
traceISR_EXIT(); \
|
||||||
|
} \
|
||||||
|
} while( 0 )
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* 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 = ( 31 - __clz( ( uxReadyPriorities ) ) )
|
||||||
|
|
||||||
|
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
extern void vPortEnterCritical( void );
|
||||||
|
extern void vPortExitCritical( void );
|
||||||
|
|
||||||
|
#define portDISABLE_INTERRUPTS() \
|
||||||
|
{ \
|
||||||
|
_set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
|
||||||
|
__asm( " dsb"); \
|
||||||
|
__asm( " isb"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 )
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb")
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||||
|
* 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 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* portNOP() is not required by this port. */
|
||||||
|
#define portNOP()
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
@@ -0,0 +1,312 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V11.3.0
|
||||||
|
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* https://www.FreeRTOS.org
|
||||||
|
* https://github.com/FreeRTOS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* FreeRTOS includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Count of the critical section nesting depth. */
|
||||||
|
uint32_t ulCriticalNesting = 9999;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Registers required to configure the RTI. */
|
||||||
|
#define portRTI_GCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC00 ) )
|
||||||
|
#define portRTI_TBCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC04 ) )
|
||||||
|
#define portRTI_COMPCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC0C ) )
|
||||||
|
#define portRTI_CNT0_FRC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC10 ) )
|
||||||
|
#define portRTI_CNT0_UC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC14 ) )
|
||||||
|
#define portRTI_CNT0_CPUC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC18 ) )
|
||||||
|
#define portRTI_CNT0_COMP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC50 ) )
|
||||||
|
#define portRTI_CNT0_UDCP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC54 ) )
|
||||||
|
#define portRTI_SETINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC80 ) )
|
||||||
|
#define portRTI_CLEARINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC84 ) )
|
||||||
|
#define portRTI_INTFLAG_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC88 ) )
|
||||||
|
|
||||||
|
|
||||||
|
/* Constants required to set up the initial stack of each task. */
|
||||||
|
#define portINITIAL_SPSR ( ( StackType_t ) 0x1F )
|
||||||
|
#define portINITIAL_FPSCR ( ( StackType_t ) 0x00 )
|
||||||
|
#define portINSTRUCTION_SIZE ( ( StackType_t ) 0x04 )
|
||||||
|
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||||
|
|
||||||
|
/* The number of words on the stack frame between the saved Top Of Stack and
|
||||||
|
R0 (in which the parameters are passed. */
|
||||||
|
#define portSPACE_BETWEEN_TOS_AND_PARAMETERS ( 12 )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* vPortStartFirstSTask() is defined in portASM.asm */
|
||||||
|
extern void vPortStartFirstTask( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Saved as part of the task context. Set to pdFALSE if the task does not
|
||||||
|
require an FPU context. */
|
||||||
|
uint32_t ulTaskHasFPUContext = 0;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||||
|
{
|
||||||
|
StackType_t *pxOriginalTOS;
|
||||||
|
|
||||||
|
pxOriginalTOS = pxTopOfStack;
|
||||||
|
|
||||||
|
#if __TI_VFP_SUPPORT__
|
||||||
|
{
|
||||||
|
/* Ensure the stack is correctly aligned on exit. */
|
||||||
|
pxTopOfStack--;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Setup the initial stack of the task. The stack is set exactly as
|
||||||
|
expected by the portRESTORE_CONTEXT() macro. */
|
||||||
|
|
||||||
|
/* First on the stack is the return address - which is the start of the as
|
||||||
|
the task has not executed yet. The offset is added to make the return
|
||||||
|
address appear as it would within an IRQ ISR. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
#ifdef portPRELOAD_TASK_REGISTERS
|
||||||
|
{
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
pxTopOfStack -= portSPACE_BETWEEN_TOS_AND_PARAMETERS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Function parameters are passed in R0. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
/* Set the status register for system mode, with interrupts enabled. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) ( ( _get_CPSR() & ~0xFF ) | portINITIAL_SPSR );
|
||||||
|
|
||||||
|
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
|
||||||
|
{
|
||||||
|
/* The task will start in thumb mode. */
|
||||||
|
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __TI_VFP_SUPPORT__
|
||||||
|
{
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
/* The last thing on the stack is the tasks ulUsingFPU value, which by
|
||||||
|
default is set to indicate that the stack frame does not include FPU
|
||||||
|
registers. */
|
||||||
|
*pxTopOfStack = pdFALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSetupTimerInterrupt(void)
|
||||||
|
{
|
||||||
|
/* Disable timer 0. */
|
||||||
|
portRTI_GCTRL_REG &= 0xFFFFFFFEUL;
|
||||||
|
|
||||||
|
/* Use the internal counter. */
|
||||||
|
portRTI_TBCTRL_REG = 0x00000000U;
|
||||||
|
|
||||||
|
/* COMPSEL0 will use the RTIFRC0 counter. */
|
||||||
|
portRTI_COMPCTRL_REG = 0x00000000U;
|
||||||
|
|
||||||
|
/* Initialise the counter and the prescale counter registers. */
|
||||||
|
portRTI_CNT0_UC0_REG = 0x00000000U;
|
||||||
|
portRTI_CNT0_FRC0_REG = 0x00000000U;
|
||||||
|
|
||||||
|
/* Set Prescalar for RTI clock. */
|
||||||
|
portRTI_CNT0_CPUC0_REG = 0x00000001U;
|
||||||
|
portRTI_CNT0_COMP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
|
||||||
|
portRTI_CNT0_UDCP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
|
||||||
|
|
||||||
|
/* Clear interrupts. */
|
||||||
|
portRTI_INTFLAG_REG = 0x0007000FU;
|
||||||
|
portRTI_CLEARINTENA_REG = 0x00070F0FU;
|
||||||
|
|
||||||
|
/* Enable the compare 0 interrupt. */
|
||||||
|
portRTI_SETINTENA_REG = 0x00000001U;
|
||||||
|
portRTI_GCTRL_REG |= 0x00000001U;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
BaseType_t xPortStartScheduler(void)
|
||||||
|
{
|
||||||
|
/* Start the timer that generates the tick ISR. */
|
||||||
|
prvSetupTimerInterrupt();
|
||||||
|
|
||||||
|
/* Reset the critical section nesting count read to execute the first task. */
|
||||||
|
ulCriticalNesting = 0;
|
||||||
|
|
||||||
|
/* Start the first task. This is done from portASM.asm as ARM mode must be
|
||||||
|
used. */
|
||||||
|
vPortStartFirstTask();
|
||||||
|
|
||||||
|
/* Should not get here! */
|
||||||
|
return pdFAIL;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
void vPortEndScheduler(void)
|
||||||
|
{
|
||||||
|
/* Not implemented in ports where there is nothing to return to.
|
||||||
|
Artificially force an assert. */
|
||||||
|
configASSERT( ulCriticalNesting == 1000UL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
|
||||||
|
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||||
|
* simply increment the system tick. */
|
||||||
|
__interrupt void vPortNonPreemptiveTick( void )
|
||||||
|
{
|
||||||
|
/* clear clock interrupt flag */
|
||||||
|
portRTI_INTFLAG_REG = 0x00000001;
|
||||||
|
|
||||||
|
/* Increment the tick count - this may make a delaying task ready
|
||||||
|
to run - but a context switch is not performed. */
|
||||||
|
xTaskIncrementTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
**************************************************************************
|
||||||
|
* The preemptive scheduler ISR is written in assembler and can be found
|
||||||
|
* in the portASM.asm file. This will only get used if portUSE_PREEMPTION
|
||||||
|
* is set to 1 in portmacro.h
|
||||||
|
**************************************************************************
|
||||||
|
*/
|
||||||
|
void vPortPreemptiveTick( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable interrupts, and keep a count of the nesting depth.
|
||||||
|
*/
|
||||||
|
void vPortEnterCritical( void )
|
||||||
|
{
|
||||||
|
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||||
|
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||||
|
portENTER_CRITICAL() has been called. */
|
||||||
|
ulCriticalNesting++;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decrement the critical nesting count, and if it has reached zero, re-enable
|
||||||
|
* interrupts.
|
||||||
|
*/
|
||||||
|
void vPortExitCritical( void )
|
||||||
|
{
|
||||||
|
if( ulCriticalNesting > 0 )
|
||||||
|
{
|
||||||
|
/* Decrement the nesting count as we are leaving a critical section. */
|
||||||
|
ulCriticalNesting--;
|
||||||
|
|
||||||
|
/* If the nesting level has reached zero then interrupts should be
|
||||||
|
re-enabled. */
|
||||||
|
if( ulCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
/* Enable interrupts as per portENABLE_INTERRUPTS(). */
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if __TI_VFP_SUPPORT__
|
||||||
|
|
||||||
|
void vPortTaskUsesFPU( void )
|
||||||
|
{
|
||||||
|
extern void vPortInitialiseFPSCR( void );
|
||||||
|
|
||||||
|
/* A task is registering the fact that it needs an FPU context. Set the
|
||||||
|
FPU flag (saved as part of the task context. */
|
||||||
|
ulTaskHasFPUContext = pdTRUE;
|
||||||
|
|
||||||
|
/* Initialise the floating point status register. */
|
||||||
|
vPortInitialiseFPSCR();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __TI_VFP_SUPPORT__ */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
;/*
|
||||||
|
; * FreeRTOS Kernel V11.3.0
|
||||||
|
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
; *
|
||||||
|
; * SPDX-License-Identifier: MIT
|
||||||
|
; *
|
||||||
|
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
; * this software and associated documentation files (the "Software"), to deal in
|
||||||
|
; * the Software without restriction, including without limitation the rights to
|
||||||
|
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
; * subject to the following conditions:
|
||||||
|
; *
|
||||||
|
; * The above copyright notice and this permission notice shall be included in all
|
||||||
|
; * copies or substantial portions of the Software.
|
||||||
|
; *
|
||||||
|
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
; *
|
||||||
|
; * https://www.FreeRTOS.org
|
||||||
|
; * https://github.com/FreeRTOS
|
||||||
|
; *
|
||||||
|
; */
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arm
|
||||||
|
.ref vTaskSwitchContext
|
||||||
|
.ref xTaskIncrementTick
|
||||||
|
.ref ulTaskHasFPUContext
|
||||||
|
.ref pxCurrentTCB
|
||||||
|
|
||||||
|
;/*-----------------------------------------------------------*/
|
||||||
|
;
|
||||||
|
; Save Task Context
|
||||||
|
;
|
||||||
|
portSAVE_CONTEXT .macro
|
||||||
|
DSB
|
||||||
|
|
||||||
|
; Push R0 as we are going to use it
|
||||||
|
STMDB SP!, {R0}
|
||||||
|
|
||||||
|
; Set R0 to point to the task stack pointer.
|
||||||
|
STMDB SP,{SP}^
|
||||||
|
SUB SP, SP, #4
|
||||||
|
LDMIA SP!,{R0}
|
||||||
|
|
||||||
|
; Push the return address onto the stack.
|
||||||
|
STMDB R0!, {LR}
|
||||||
|
|
||||||
|
; Now LR has been saved, it can be used instead of R0.
|
||||||
|
MOV LR, R0
|
||||||
|
|
||||||
|
; Pop R0 so it can be saved onto the task stack.
|
||||||
|
LDMIA SP!, {R0}
|
||||||
|
|
||||||
|
; Push all the system mode registers onto the task stack.
|
||||||
|
STMDB LR,{R0-LR}^
|
||||||
|
SUB LR, LR, #60
|
||||||
|
|
||||||
|
; Push the SPSR onto the task stack.
|
||||||
|
MRS R0, SPSR
|
||||||
|
STMDB LR!, {R0}
|
||||||
|
|
||||||
|
.if (__TI_VFP_SUPPORT__)
|
||||||
|
;Determine if the task maintains an FPU context.
|
||||||
|
LDR R0, ulFPUContextConst
|
||||||
|
LDR R0, [R0]
|
||||||
|
|
||||||
|
; Test the flag
|
||||||
|
CMP R0, #0
|
||||||
|
|
||||||
|
; If the task is not using a floating point context then skip the
|
||||||
|
; saving of the FPU registers.
|
||||||
|
BEQ $+16
|
||||||
|
FSTMDBD LR!, {D0-D15}
|
||||||
|
FMRX R1, FPSCR
|
||||||
|
STMFD LR!, {R1}
|
||||||
|
|
||||||
|
; Save the flag
|
||||||
|
STMDB LR!, {R0}
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; Store the new top of stack for the task.
|
||||||
|
LDR R0, pxCurrentTCBConst
|
||||||
|
LDR R0, [R0]
|
||||||
|
STR LR, [R0]
|
||||||
|
|
||||||
|
.endm
|
||||||
|
|
||||||
|
;/*-----------------------------------------------------------*/
|
||||||
|
;
|
||||||
|
; Restore Task Context
|
||||||
|
;
|
||||||
|
portRESTORE_CONTEXT .macro
|
||||||
|
LDR R0, pxCurrentTCBConst
|
||||||
|
LDR R0, [R0]
|
||||||
|
LDR LR, [R0]
|
||||||
|
|
||||||
|
.if (__TI_VFP_SUPPORT__)
|
||||||
|
; The floating point context flag is the first thing on the stack.
|
||||||
|
LDR R0, ulFPUContextConst
|
||||||
|
LDMFD LR!, {R1}
|
||||||
|
STR R1, [R0]
|
||||||
|
|
||||||
|
; Test the flag
|
||||||
|
CMP R1, #0
|
||||||
|
|
||||||
|
; If the task is not using a floating point context then skip the
|
||||||
|
; VFP register loads.
|
||||||
|
BEQ $+16
|
||||||
|
|
||||||
|
; Restore the floating point context.
|
||||||
|
LDMFD LR!, {R0}
|
||||||
|
FLDMIAD LR!, {D0-D15}
|
||||||
|
FMXR FPSCR, R0
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; Get the SPSR from the stack.
|
||||||
|
LDMFD LR!, {R0}
|
||||||
|
MSR SPSR_CSXF, R0
|
||||||
|
|
||||||
|
; Restore all system mode registers for the task.
|
||||||
|
LDMFD LR, {R0-R14}^
|
||||||
|
|
||||||
|
; Restore the return address.
|
||||||
|
LDR LR, [LR, #+60]
|
||||||
|
|
||||||
|
; And return - correcting the offset in the LR to obtain the
|
||||||
|
; correct address.
|
||||||
|
SUBS PC, LR, #4
|
||||||
|
.endm
|
||||||
|
|
||||||
|
;/*-----------------------------------------------------------*/
|
||||||
|
; Start the first task by restoring its context.
|
||||||
|
|
||||||
|
.def vPortStartFirstTask
|
||||||
|
|
||||||
|
vPortStartFirstTask:
|
||||||
|
portRESTORE_CONTEXT
|
||||||
|
|
||||||
|
;/*-----------------------------------------------------------*/
|
||||||
|
; Yield to another task.
|
||||||
|
|
||||||
|
.def vPortYieldProcessor
|
||||||
|
|
||||||
|
vPortYieldProcessor:
|
||||||
|
; Within an IRQ ISR the link register has an offset from the true return
|
||||||
|
; address. SWI doesn't do this. Add the offset manually so the ISR
|
||||||
|
; return code can be used.
|
||||||
|
ADD LR, LR, #4
|
||||||
|
|
||||||
|
; First save the context of the current task.
|
||||||
|
portSAVE_CONTEXT
|
||||||
|
|
||||||
|
; Select the next task to execute. */
|
||||||
|
BL vTaskSwitchContext
|
||||||
|
|
||||||
|
; Restore the context of the task selected to execute.
|
||||||
|
portRESTORE_CONTEXT
|
||||||
|
|
||||||
|
;/*-----------------------------------------------------------*/
|
||||||
|
; Yield to another task from within the FreeRTOS API
|
||||||
|
|
||||||
|
.def vPortYeildWithinAPI
|
||||||
|
|
||||||
|
vPortYeildWithinAPI:
|
||||||
|
; Save the context of the current task.
|
||||||
|
|
||||||
|
portSAVE_CONTEXT
|
||||||
|
; Clear SSI flag.
|
||||||
|
MOVW R0, #0xFFF4
|
||||||
|
MOVT R0, #0xFFFF
|
||||||
|
LDR R0, [R0]
|
||||||
|
|
||||||
|
; Select the next task to execute. */
|
||||||
|
BL vTaskSwitchContext
|
||||||
|
|
||||||
|
; Restore the context of the task selected to execute.
|
||||||
|
portRESTORE_CONTEXT
|
||||||
|
|
||||||
|
;/*-----------------------------------------------------------*/
|
||||||
|
; Preemptive Tick
|
||||||
|
|
||||||
|
.def vPortPreemptiveTick
|
||||||
|
|
||||||
|
vPortPreemptiveTick:
|
||||||
|
|
||||||
|
; Save the context of the current task.
|
||||||
|
portSAVE_CONTEXT
|
||||||
|
|
||||||
|
; Clear interrupt flag
|
||||||
|
MOVW R0, #0xFC88
|
||||||
|
MOVT R0, #0xFFFF
|
||||||
|
MOV R1, #1
|
||||||
|
STR R1, [R0]
|
||||||
|
|
||||||
|
; Increment the tick count, making any adjustments to the blocked lists
|
||||||
|
; that may be necessary.
|
||||||
|
BL xTaskIncrementTick
|
||||||
|
|
||||||
|
; Select the next task to execute.
|
||||||
|
CMP R0, #0
|
||||||
|
BLNE vTaskSwitchContext
|
||||||
|
|
||||||
|
; Restore the context of the task selected to execute.
|
||||||
|
portRESTORE_CONTEXT
|
||||||
|
|
||||||
|
;-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.if (__TI_VFP_SUPPORT__)
|
||||||
|
|
||||||
|
.def vPortInitialiseFPSCR
|
||||||
|
|
||||||
|
vPortInitialiseFPSCR:
|
||||||
|
|
||||||
|
MOV R0, #0
|
||||||
|
FMXR FPSCR, R0
|
||||||
|
BX LR
|
||||||
|
|
||||||
|
.endif ;__TI_VFP_SUPPORT__
|
||||||
|
|
||||||
|
|
||||||
|
pxCurrentTCBConst .word pxCurrentTCB
|
||||||
|
ulFPUContextConst .word ulTaskHasFPUContext
|
||||||
|
;-------------------------------------------------------------------------------
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user